Notes For V3.6-0

The save/restore format has been updated to improve its reliability.
As a result, save files prior to release 3.0 are no longer supported.

The text documentation files are obsolete and are no longer included
with the distribution.  Up-to-date PDF documentation files are
available on the SimH web site.

1. New Features

1.1 3.6-0

1.1.1 Most magnetic tapes

- Added support for limiting tape capacity to a particular size in MB

1.1.2 IBM 7090/7094

- First release

1.1.3 VAX-11/780

- Added FLOAD command, loads system file from console floppy disk

1.1.4 VAX, VAX-11/780, and PDP-11

- Added card reader support (from John Dundas)

1.1.5 PDP-11

- Added instruction history

2. Bugs Fixed

Please see the revision history on http://simh.trailing-edge.com or
in the source module sim_rev.h.
This commit is contained in:
Bob Supnik 2006-05-27 11:34:00 -07:00 committed by Mark Pizzolato
parent a12e4a1c39
commit dc871fa631
106 changed files with 15439 additions and 17517 deletions

View file

@ -1,148 +0,0 @@
Notes For V3.5-1
The source set has been extensively overhauled. For correct
viewing, set Visual C++ or Emacs to have tab stops every 4
characters.
1. New Features
1.1 3.5-0
1.1.1 All Ethernet devices
- Added Windows user-defined adapter names (from Timothe Litt)
1.1.2 Interdata, SDS, HP, PDP-8, PDP-18b terminal multiplexors
- Added support for SET <unit>n DISCONNECT
1.1.3 VAX
- Added latent QDSS support
- Revised autoconfigure to handle QDSS
1.1.4 PDP-11
- Revised autoconfigure to handle more cases
1.2 3.5-1
No new features
1.3 3.5-2
1.3.1 All ASCII terminals
- Most ASCII terminal emulators have supported 7-bit and 8-bit
operation; where required, they have also supported an upper-
case only or KSR-emulation mode. This release adds a new mode,
7P, for 7-bit printing characters. In 7P mode, non-printing
characters in the range 0-31 (decimal), and 127 (decimal), are
automatically suppressed. This prevents printing of fill
characters under Windows.
The printable character set for ASCII code values 0-31 can be
changed with the SET CONSOLE PCHAR command. Code value 127
(DELETE) is always suppressed.
1.3.2 VAX-11/780
- First release. The VAX-11/780 has successfully run VMS V7.2. The
commercial instructions and compatability mode have not been
extensively tested. The Ethernet controller is not working yet
and is disabled.
2. Bugs Fixed
2.1 3.5-0
2.1.1 SCP and libraries
- Trim trailing spaces on all input (for example, attach file names)
- Fixed sim_sock spurious SIGPIPE error in Unix/Linux
- Fixed sim_tape misallocation of TPC map array for 64b simulators
2.1.2 1401
- Fixed bug, CPU reset was clearing SSB through SSG
2.1.3 PDP-11
- Fixed bug in VH vector display routine
- Fixed XU runt packet processing (found by Tim Chapman)
2.1.4 Interdata
- Fixed bug in SHOW PAS CONN/STATS
- Fixed potential integer overflow exception in divide
2.1.5 SDS
- Fixed bug in SHOW MUX CONN/STATS
2.1.6 HP
- Fixed bug in SHOW MUX CONN/STATS
2.1.7 PDP-8
- Fixed bug in SHOW TTIX CONN/STATS
- Fixed bug in SET/SHOW TTOXn LOG
2.1.8 PDP-18b
- Fixed bug in SHOW TTIX CONN/STATS
- Fixed bug in SET/SHOW TTOXn LOG
2.1.9 Nova, Eclipse
- Fixed potential integer overflow exception in divide
2.2 3.5-1
2.2.1 1401
- Changed character encodings to be compatible with Pierce 709X simulator
- Added mode for old/new character encodings
2.2.2 1620
- Changed character encodings to be compatible with Pierce 709X simulator
2.2.3 PDP-10
- Changed MOVNI to eliminate GCC warning
2.2.4 VAX
- Fixed bug in structure definitions with 32b compilation options
- Fixed bug in autoconfiguration table
2.2.5 PDP-11
- Fixed bug in autoconfiguration table
2.3 3.5-2
2.3.1 PDP-10
- RP: fixed drive clear not to clear disk address
2.3.2 PDP-11 (VAX, VAX-11/780, for shared peripherals)
- HK: fixed overlap seek interaction with drive select, drive clear, etc
- RQ, TM, TQ, TS, TU: widened address display to 64b when USE_ADDR64 option selected
- TU: changed default adapter from TM02 to TM03 (required by VMS)
- RP: fixed drive clear not to clear disk address
- RP, TU: fixed device enable/disable to enabled/disable Massbus adapter as well
- XQ: fixed register access alignment bug (found by Doug Carman)
2.3.3 PDP-8
- RL: fixed IOT 61 decoding bug (found by David Gesswein)
- DF, DT, RF: fixed register access alignment bug (found by Doug Carman)
2.3.4 VAX
- Fixed CVTfi to trap on integer overflow if PSW<iv> is set
- Fixed breakpoint detection when USE_ADDR64 option selected

39
0readme_36.txt Normal file
View file

@ -0,0 +1,39 @@
Notes For V3.6-0
The save/restore format has been updated to improve its reliability.
As a result, save files prior to release 3.0 are no longer supported.
The text documentation files are obsolete and are no longer included
with the distribution. Up-to-date PDF documentation files are
available on the SimH web site.
1. New Features
1.1 3.6-0
1.1.1 Most magnetic tapes
- Added support for limiting tape capacity to a particular size in MB
1.1.2 IBM 7090/7094
- First release
1.1.3 VAX-11/780
- Added FLOAD command, loads system file from console floppy disk
1.1.4 VAX, VAX-11/780, and PDP-11
- Added card reader support (from John Dundas)
1.1.5 PDP-11
- Added instruction history
2. Bugs Fixed
Please see the revision history on http://simh.trailing-edge.com or
in the source module sim_rev.h.

File diff suppressed because it is too large Load diff

View file

@ -1,6 +1,6 @@
/* altairz80_defs.h: MITS Altair simulator definitions /* altairz80_defs.h: MITS Altair simulator definitions
Copyright (c) 2002-2005, Peter Schorn Copyright (c) 2002-2006, Peter Schorn
Permission is hereby granted, free of charge, to any person obtaining a Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"), copy of this software and associated documentation files (the "Software"),
@ -73,14 +73,3 @@
sprintf(messageBuffer,PCformat p1,PCX,p2,p3,p4,p5); printMessage() sprintf(messageBuffer,PCformat p1,PCX,p2,p3,p4,p5); printMessage()
#define message6(p1,p2,p3,p4,p5,p6) \ #define message6(p1,p2,p3,p4,p5,p6) \
sprintf(messageBuffer,PCformat p1,PCX,p2,p3,p4,p5,p6); printMessage() sprintf(messageBuffer,PCformat p1,PCX,p2,p3,p4,p5,p6); printMessage()
/* The default is to use "inline". */
#if defined(NO_INLINE)
#define INLINE
#else
#if defined(__DECC) && defined(VMS)
#define INLINE __inline
#else
#define INLINE inline
#endif
#endif

View file

@ -1,6 +1,6 @@
/* altairz80_dsk.c: MITS Altair 88-DISK Simulator /* altairz80_dsk.c: MITS Altair 88-DISK Simulator
Copyright (c) 2002-2005, Peter Schorn Copyright (c) 2002-2006, Peter Schorn
Permission is hereby granted, free of charge, to any person obtaining a Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"), copy of this software and associated documentation files (the "Software"),
@ -494,7 +494,7 @@ int32 dsk11(const int32 port, const int32 io, const int32 data) {
/* Disk Data In/Out */ /* Disk Data In/Out */
static INLINE int32 dskseek(const UNIT *xptr) { static int32 dskseek(const UNIT *xptr) {
return fseek(xptr -> fileref, DSK_TRACSIZE * current_track[current_disk] + return fseek(xptr -> fileref, DSK_TRACSIZE * current_track[current_disk] +
DSK_SECTSIZE * current_sector[current_disk], SEEK_SET); DSK_SECTSIZE * current_sector[current_disk], SEEK_SET);
} }

View file

@ -1,6 +1,6 @@
/* altairz80_sio: MITS Altair serial I/O card /* altairz80_sio.c: MITS Altair serial I/O card
Copyright (c) 2002-2005, Peter Schorn Copyright (c) 2002-2006, Peter Schorn
Permission is hereby granted, free of charge, to any person obtaining a Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"), copy of this software and associated documentation files (the "Software"),
@ -115,7 +115,7 @@ extern t_stat sim_poll_kbd(void);
extern t_stat sim_putchar(int32 out); extern t_stat sim_putchar(int32 out);
extern t_stat attach_unit(UNIT *uptr, char *cptr); extern t_stat attach_unit(UNIT *uptr, char *cptr);
extern int32 getBankSelect(void); extern int32 getBankSelect(void);
extern void setBankSelect(int32 b); extern void setBankSelect(const int32 b);
extern uint32 getCommon(void); extern uint32 getCommon(void);
extern t_bool rtc_avail; extern t_bool rtc_avail;
extern FILE *sim_log; extern FILE *sim_log;
@ -124,7 +124,7 @@ extern int32 sim_switches;
extern uint32 sim_os_msec(void); extern uint32 sim_os_msec(void);
extern const char *scp_error_messages[]; extern const char *scp_error_messages[];
extern int32 SR; extern int32 SR;
extern uint8 GetBYTEWrapper(register uint32 Addr); extern uint8 GetBYTEWrapper(const uint32 Addr);
extern UNIT cpu_unit; extern UNIT cpu_unit;
/* SIMH pseudo device status registers */ /* SIMH pseudo device status registers */

View file

@ -1,6 +1,6 @@
/* altairz80_sys.c: MITS Altair system interface /* altairz80_sys.c: MITS Altair system interface
Copyright (c) 2002-2005, Peter Schorn Copyright (c) 2002-2006, Peter Schorn
Permission is hereby granted, free of charge, to any person obtaining a Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"), copy of this software and associated documentation files (the "Software"),
@ -584,7 +584,7 @@ static int32 match(const char *pattern, const char *input, char *xyFirst, char *
return (pat == 0) && (inp == 0); return (pat == 0) && (inp == 0);
} }
static INLINE int32 checkXY(const char xy) { static int32 checkXY(const char xy) {
return xy == 'X' ? 0xdd : 0xfd; /* else is 'Y' */ return xy == 'X' ? 0xdd : 0xfd; /* else is 'Y' */
} }

View file

@ -1,6 +1,6 @@
/* altairz80_hdsk.c: simulated hard disk device to increase capacity /* altairz80_hdsk.c: simulated hard disk device to increase capacity
Copyright (c) 2002-2005, Peter Schorn Copyright (c) 2002-2006, Peter Schorn
Permission is hereby granted, free of charge, to any person obtaining a Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"), copy of this software and associated documentation files (the "Software"),
@ -54,9 +54,9 @@ extern int32 saved_PC;
extern int32 install_bootrom(void); extern int32 install_bootrom(void);
extern void printMessage(void); extern void printMessage(void);
extern void PutBYTEBasic(const uint32 Addr, const uint32 Bank, const uint32 Value); extern void PutBYTEBasic(const uint32 Addr, const uint32 Bank, const uint32 Value);
extern void PutBYTEWrapper(register uint32 Addr, register uint32 Value); extern void PutBYTEWrapper(const uint32 Addr, const uint32 Value);
extern void protect(const int32 l, const int32 h); extern void protect(const int32 l, const int32 h);
extern uint8 GetBYTEWrapper(register uint32 Addr); extern uint8 GetBYTEWrapper(const uint32 Addr);
extern int32 bootrom[bootrom_size]; extern int32 bootrom[bootrom_size];
static t_stat hdsk_svc(UNIT *uptr); static t_stat hdsk_svc(UNIT *uptr);

View file

@ -1,338 +0,0 @@
To: Users
From: Bob Supnik
Subj: GRI-909 Simulator Usage
Date: 01-Dec-2005
COPYRIGHT NOTICE
The following copyright notice applies to both the SIMH source and binary:
Original code published in 1993-2005, written by Robert M Supnik
Copyright (c) 1993-2005, Robert M Supnik
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Except as contained in this notice, the name of Robert M Supnik shall not be
used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from Robert M Supnik.
This memorandum documents the GRI-909 simulator.
1. Simulator Files
sim/ scp.h
sim_console.h
sim_defs.h
sim_fio.h
sim_rev.h
sim_sock.h
sim_timer.h
sim_tmxr.h
scp.c
sim_console.c
sim_fio.c
sim_sock.c
sim_timer.c
sim_tmxr.c
sim/gri/ gri_defs.h
gri_cpu.c
gri_stddev.c
gri_sys.c
2. GRI-909 Features
The GRI-909 is configured as follows:
device simulates
name(s)
CPU GRI-909 CPU with up to 32KW of memory
HSR S42-004 high speed reader
HSP S42-004 high speed punch
TTI S42-001 Teletype input
TTO S42-002 Teletype output
RTC real-time clock
The GRI-909 simulator implements the following unique stop conditions:
- an unimplemented operator is referenced, and register
STOP_OPR is set
- an invalid interrupt request is made
The LOAD commands has an optional argument to specify the load address:
LOAD <filename> {<starting address>}
The LOAD command loads a paper-tape bootstrap format file at the specified
address. If no address is specified, loading starts at location 200. The
DUMP command is not supported.
2.1 CPU
The only CPU options are the presence of the extended arithmetic operator
and the size of main memory.
SET CPU EAO enable extended arithmetic operator
SET CPU NOEAO disable extended arithmetic operator
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
If memory size is being reduced, and the memory being truncated contains
non-zero data, the simulator asks for confirmation. Data in the truncated
portion of memory is lost. Initial memory size is 32K.
CPU registers include the visible state of the processor as well as the
control registers for the interrupt system.
name size comments
SC 15 sequence counter
AX 16 arithmetic operator input register 1
AY 16 arithmetic operator input register 2
AO 16 arithmetic operator output register
TRP 16 TRP register
MSR 16 machine status register
ISR 16 interrupt status register
BSW 16 byte swapper buffer
BPK 16 byte packer buffer
GR1..GR6 16 general registers 1 to 6
BOV 1 bus overflow (MSR<15>)
L 1 link (MSR<14>)
FOA 2 arithmetic operator function (MSR<9:8>)
AOV 1 arithmetic overflow (MSR<0>)
IR 16 instruction register (read only)
MA 16 memory address register (read only)
SWR 16 switch register
DR 16 display register
THW 6 thumbwheels (selects operator displayed in DR)
IREQ 16 interrupt requests
ION 1 interrupts enabled
INODEF 1 interrupts not deferred
BKP 1 breakpoint request
SCQ[0:63] 15 SC prior to last jump or interrupt;
most recent SC change first
STOP_OPR 1 stop on undefined operator
WRU 8 interrupt character
2.2 Programmed I/O Devices
2.2.1 S42-004 High Speed Reader (HSR)
The paper tape reader (HSR) reads data from or a disk file. The POS
register specifies the number of the next data item to be read.
Thus, by changing POS, the user can backspace or advance the reader.
The paper tape reader implements these registers:
name size comments
BUF 8 last data item processed
IRDY 1 device ready flag
IENB 1 device interrupt enable flag
POS 32 position in the input file
TIME 24 time from I/O initiation to interrupt
STOP_IOE 1 stop on I/O error
Error handling is as follows:
error STOP_IOE processed as
not attached 1 report error and stop
0 out of tape
end of file 1 report error and stop
0 out of tape
OS I/O error x report error and stop
2.2.2 S42-006 High Speed Punch (HSP)
The paper tape punch (HSP) writes data to a disk file. The POS
register specifies the number of the next data item to be written.
Thus, by changing POS, the user can backspace or advance the punch.
The paper tape punch implements these registers:
name size comments
BUF 8 last data item processed
ORDY 1 device ready flag
IENB 1 device interrupt enable flag
POS 32 position in the output file
TIME 24 time from I/O initiation to interrupt
STOP_IOE 1 stop on I/O error
Error handling is as follows:
error STOP_IOE processed as
not attached 1 report error and stop
0 out of tape
OS I/O error x report error and stop
2.2.3 S42-001 Teletype Input (TTI)
The Teletype interfaces (TTI, TTO) can be set to one of four modes,
KSR, 7P, 7B, or 8B:
mode input characters output characters
KSR lower case converted lower case converted
to upper case, to upper case,
high-order bit set high-order bit cleared,
non-printing characters
suppressed
7P high-order bit cleared high-order bit cleared,
non-printing characters
suppressed
7B high-order bit cleared high-order bit cleared
8B no changes no changes
The default mode is KSR.
The Teletype input (TTI) polls the console keyboard for input. It
implements these registers:
name size comments
BUF 8 last data item processed
IRDY 1 device ready flag
IENB 1 device interrupt enable flag
POS 32 position in the output file
TIME 24 keyboard polling interval
2.2.4 S42-002 Teletype Output (TTO)
The Teletype output (TTO) writes to the simulator console window. It
implements these registers:
name size comments
BUF 8 last data item processed
ORDY 1 device ready flag
IENB 1 device interrupt enable flag
POS 32 number of characters output
TIME 24 time from I/O initiation to interrupt
2.2.5 Real-Time Clock (RTC)
The real-time clock (CLK) implements these registers:
name size comments
RDY 1 device ready flag
IENB 1 interrupt enable flag
TIME 24 clock interval
The real-time clock autocalibrates; the clock interval is adjusted up or
down so that the clock tracks actual elapsed time.
2.3 Symbolic Display and Input
The GRI-909 simulator implements symbolic display and input. Display is
controlled by command line switches:
-a display as ASCII character
-c display as packed ASCII characters
-m display instruction mnemonics
Input parsing is controlled by the first character typed in or by command
line switches:
' or -a ASCII character
" or -c two packed ASCII characters
alphabetic instruction mnemonic
numeric octal number
Instruction input uses modified GRI-909 basic assembler syntax. There are
thirteen different instruction formats. Operators, functions, and tests may
be octal or symbolic; jump conditions and bus operators are always symbolic.
Function out, general
Syntax: FO function,operator
Function symbols: INP, IRDY, ORDY, STRT
Example: FO ORDY,TTO
Function out, named
Syntax: FO{M|I|A} function
Function symbols: M: CLL, CML, STL, HLT; I: ICF, ICO;
A: ADD, AND, XOR, OR
Example: FOA XOR
Sense function, general
Syntax: SF operator,{NOT} tests
Test symbols: IRDY, ORDY
Example: SF HSR,IRDY
Sense function, named
Syntax: SF{M|A} {NOT} tests
Test symbols: M: POK BOV LNK; A: SOV AOV
Example: SFM NOT BOV
Register to register
Syntax: RR{C} src,{bus op,}dst
Bus op symbols: P1, L1, R1
Example: RRC AX,P1,AY
Zero to register
Syntax: ZR{C} {bus op,}dst
Bus op symbols: P1, L1, R1
Example: ZR P1,GR1
Register to self
Syntax: RS{C} dst{,bus op}
Bus op symbols: P1, L1, R1
Example: RS AX,L1
Jump unconditional or named condition
Syntax: J{U|O|N}{D} address
Example: JUD 1400
Jump conditional
Syntax: JC{D} src,cond,address
Cond symbols: NEVER,ALWAYS,ETZ,NEZ,LTZ,GEZ,LEZ,GTZ
Example: JC AX,LEZ,200
Register to memory
syntax: RM{I|D|ID} src,{bus op,}address
Bus op symbols: P1, L1, R1
Example: RMD AX,P1,1315
Zero to memory
Syntax: ZM{I|D|ID} {bus op,}address
Bus op symbols: P1, L1, R1
Example: ZM P1,5502
Memory to register
Syntax: MR{I|D|ID} address,{bus op,}dst
Bus op symbols: P1, L1, R1
Example: MRI 1405,GR6
Memory to self:
Syntax: MS{I|D|ID} address{,bus op}
Bus op symbols: P1, L1, R1
Example: MS 3333,P1

View file

@ -1,6 +1,6 @@
/* h316_cpu.c: Honeywell 316/516 CPU simulator /* h316_cpu.c: Honeywell 316/516 CPU simulator
Copyright (c) 1999-2005, Robert M. Supnik Copyright (c) 1999-2006, Robert M. Supnik
Permission is hereby granted, free of charge, to any person obtaining a Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"), copy of this software and associated documentation files (the "Software"),
@ -25,6 +25,7 @@
cpu H316/H516 CPU cpu H316/H516 CPU
03-Apr-06 RMS Fixed bugs in LLL, LRL (from Theo Engel)
22-Sep-05 RMS Fixed declarations (from Sterling Garwood) 22-Sep-05 RMS Fixed declarations (from Sterling Garwood)
16-Aug-05 RMS Fixed C++ declaration and cast problems 16-Aug-05 RMS Fixed C++ declaration and cast problems
15-Feb-05 RMS Added start button interrupt 15-Feb-05 RMS Added start button interrupt
@ -427,7 +428,7 @@ if (chan_req) { /* channel request? */
if (st & DMA_IN) { /* input? */ if (st & DMA_IN) { /* input? */
t = iotab[dev] (ioINA, 0, 0, dev); /* input word */ t = iotab[dev] (ioINA, 0, 0, dev); /* input word */
if ((t & IOT_SKIP) == 0) return STOP_DMAER; if ((t & IOT_SKIP) == 0) return STOP_DMAER;
if (r = (t >> IOT_V_REASON)) return r; if ((r = t >> IOT_V_REASON) != 0) return r;
Write (ad, t & DMASK); /* write to mem */ Write (ad, t & DMASK); /* write to mem */
} }
else { /* no, output */ else { /* no, output */
@ -441,7 +442,7 @@ if (chan_req) { /* channel request? */
if (dma_wc[i] == 0) { /* done? */ if (dma_wc[i] == 0) { /* done? */
dma_eor[i] = 1; /* set end of range */ dma_eor[i] = 1; /* set end of range */
t = iotab[dev] (ioEND, 0, 0, dev); /* send end range */ t = iotab[dev] (ioEND, 0, 0, dev); /* send end range */
if (r = (t >> IOT_V_REASON)) return r; if ((r = t >> IOT_V_REASON) != 0) return r;
} }
} }
else { /* DMC */ else { /* DMC */
@ -450,7 +451,7 @@ if (chan_req) { /* channel request? */
end = Read (dmcad + 1); /* get end */ end = Read (dmcad + 1); /* get end */
if (((ad ^ end) & X_AMASK) == 0) { /* start == end? */ if (((ad ^ end) & X_AMASK) == 0) { /* start == end? */
t = iotab[dev] (ioEND, 0, 0, dev); /* send end range */ t = iotab[dev] (ioEND, 0, 0, dev); /* send end range */
if (r = (t >> IOT_V_REASON)) return r; if ((r = t >> IOT_V_REASON) != 0) return r;
} /* end if end range */ } /* end if end range */
} /* end else DMC */ } /* end else DMC */
} /* end if chan i */ } /* end if chan i */
@ -659,6 +660,7 @@ switch (I_GETOP (MB)) { /* case on <1:6> */
case 000: case 000:
if ((MB & 1) == 0) { /* HLT */ if ((MB & 1) == 0) { /* HLT */
if ((reason = sim_process_event ()) != SCPE_OK) break;
reason = STOP_HALT; reason = STOP_HALT;
break; break;
} }
@ -739,7 +741,8 @@ switch (I_GETOP (MB)) { /* case on <1:6> */
else { else {
ut = GETDBL_U (AR, BR); /* get A'B */ ut = GETDBL_U (AR, BR); /* get A'B */
C = (ut >> (t1 - 1)) & 1; /* C = last out */ C = (ut >> (t1 - 1)) & 1; /* C = last out */
ut = ut >> t1; /* log right */ if (t1 == 32) ut = 0; /* =32? all 0 */
else ut = ut >> t1; /* log right */
} }
PUTDBL_U (ut); /* store A,B */ PUTDBL_U (ut); /* store A,B */
break; break;
@ -803,7 +806,8 @@ switch (I_GETOP (MB)) { /* case on <1:6> */
else { else {
ut = GETDBL_U (AR, BR); /* get A'B */ ut = GETDBL_U (AR, BR); /* get A'B */
C = (ut >> (32 - t1)) & 1; /* C = last out */ C = (ut >> (32 - t1)) & 1; /* C = last out */
ut = ut << t1; /* log left */ if (t1 == 32) ut = 0; /* =32? all 0 */
else ut = ut << t1; /* log left */
} }
PUTDBL_U (ut); /* store A,B */ PUTDBL_U (ut); /* store A,B */
break; break;
@ -879,7 +883,7 @@ switch (I_GETOP (MB)) { /* case on <1:6> */
((MB & 000020) && ss[0]) || /* SS1 */ ((MB & 000020) && ss[0]) || /* SS1 */
((MB & 000040) && AR) || /* SNZ */ ((MB & 000040) && AR) || /* SNZ */
((MB & 000100) && (AR & 1)) || /* SLN */ ((MB & 000100) && (AR & 1)) || /* SLN */
((MB & 000200) && (TST_INTREQ (INT_MPE))) || /* SPS */ ((MB & 000200) && (TST_INTREQ (INT_MPE))) || /* SPS */
((MB & 000400) && (AR & SIGN))) skip = 1; /* SMI */ ((MB & 000400) && (AR & SIGN))) skip = 1; /* SMI */
if ((MB & 001000) == 0) skip = skip ^ 1; /* reverse? */ if ((MB & 001000) == 0) skip = skip ^ 1; /* reverse? */
PC = NEWA (PC, PC + skip); PC = NEWA (PC, PC + skip);
@ -895,12 +899,12 @@ switch (I_GETOP (MB)) { /* case on <1:6> */
else if (MB == 0140320) { /* CSA */ else if (MB == 0140320) { /* CSA */
C = (AR & SIGN) >> 15; C = (AR & SIGN) >> 15;
AR = AR & ~SIGN; AR = AR & ~SIGN;
} }
else if (MB == 0140401) AR = AR ^ DMASK; /* CMA */ else if (MB == 0140401) AR = AR ^ DMASK; /* CMA */
else if (MB == 0140407) { /* TCA */ else if (MB == 0140407) { /* TCA */
AR = (-AR) & DMASK; AR = (-AR) & DMASK;
sc = 0; sc = 0;
} }
else if (MB == 0140500) AR = AR | SIGN; /* SSM */ else if (MB == 0140500) AR = AR | SIGN; /* SSM */
else if (MB == 0140600) C = 1; /* SCB */ else if (MB == 0140600) C = 1; /* SCB */
else if (MB == 0141044) AR = AR & 0177400; /* CAR */ else if (MB == 0141044) AR = AR & 0177400; /* CAR */
@ -1369,9 +1373,11 @@ for (i = 0; dptr = sim_devices[i]; i++) { /* loop thru devices */
dno = dibp->dev; /* device number */ dno = dibp->dev; /* device number */
for (j = 0; j < dibp->num; j++) { /* repeat for slots */ for (j = 0; j < dibp->num; j++) { /* repeat for slots */
if (iotab[dno + j]) { /* conflict? */ if (iotab[dno + j]) { /* conflict? */
printf ("%s device number conflict, devno = %02o\n", sim_dname (dptr), dno + j); printf ("%s device number conflict, devno = %02o\n",
sim_dname (dptr), dno + j);
if (sim_log) fprintf (sim_log, if (sim_log) fprintf (sim_log,
"%s device number conflict, devno = %02o\n", sim_dname (dptr), dno + j); "%s device number conflict, devno = %02o\n",
sim_dname (dptr), dno + j);
return TRUE; return TRUE;
} }
iotab[dno + j] = dibp->io; /* set I/O routine */ iotab[dno + j] = dibp->io; /* set I/O routine */
@ -1379,21 +1385,27 @@ for (i = 0; dptr = sim_devices[i]; i++) { /* loop thru devices */
if (dibp->chan) { /* DMA/DMC? */ if (dibp->chan) { /* DMA/DMC? */
chan = dibp->chan - 1; chan = dibp->chan - 1;
if ((chan < DMC_V_DMC1) && (chan >= dma_nch)) { if ((chan < DMC_V_DMC1) && (chan >= dma_nch)) {
printf ("%s configured for DMA channel %d\n", sim_dname (dptr), chan + 1); printf ("%s configured for DMA channel %d\n",
sim_dname (dptr), chan + 1);
if (sim_log) fprintf (sim_log, if (sim_log) fprintf (sim_log,
"%s configured for DMA channel %d\n", sim_dname (dptr), chan + 1); "%s configured for DMA channel %d\n",
sim_dname (dptr), chan + 1);
return TRUE; return TRUE;
} }
if ((chan >= DMC_V_DMC1) && !(cpu_unit.flags & UNIT_DMC)) { if ((chan >= DMC_V_DMC1) && !(cpu_unit.flags & UNIT_DMC)) {
printf ("%s configured for DMC, option disabled\n", sim_dname (dptr)); printf ("%s configured for DMC, option disabled\n",
sim_dname (dptr));
if (sim_log) fprintf (sim_log, if (sim_log) fprintf (sim_log,
"%s configured for DMC, option disabled\n", sim_dname (dptr)); "%s configured for DMC, option disabled\n",
sim_dname (dptr));
return TRUE; return TRUE;
} }
if (chan_map[chan]) { /* channel conflict? */ if (chan_map[chan]) { /* channel conflict? */
printf ("%s DMA/DMC channel conflict, devno = %02o\n", sim_dname (dptr), dno); printf ("%s DMA/DMC channel conflict, devno = %02o\n",
sim_dname (dptr), dno);
if (sim_log) fprintf (sim_log, if (sim_log) fprintf (sim_log,
"%s DMA/DMC channel conflict, devno = %02o\n", sim_dname (dptr), dno); "%s DMA/DMC channel conflict, devno = %02o\n",
sim_dname (dptr), dno);
return TRUE; return TRUE;
} }
chan_map[chan] = dno; /* channel back map */ chan_map[chan] = dno; /* channel back map */
@ -1466,7 +1478,8 @@ for (k = 0; k < lnt; k++) { /* print specified */
if (h->pc & HIST_EA) fprintf (st, "%05o ", h->ea); if (h->pc & HIST_EA) fprintf (st, "%05o ", h->ea);
else fprintf (st, " "); else fprintf (st, " ");
sim_eval = h->ir; sim_eval = h->ir;
if ((fprint_sym (st, h->pc & X_AMASK, &sim_eval, &cpu_unit, SWMASK ('M'))) > 0) if ((fprint_sym (st, h->pc & X_AMASK, &sim_eval,
&cpu_unit, SWMASK ('M'))) > 0)
fprintf (st, "(undefined) %06o", h->ir); fprintf (st, "(undefined) %06o", h->ir);
op = I_GETOP (h->ir) & 017; /* base op */ op = I_GETOP (h->ir) & 017; /* base op */
if (has_opnd[op]) fprintf (st, " [%06o]", h->opnd); if (has_opnd[op]) fprintf (st, " [%06o]", h->opnd);

View file

@ -1,672 +0,0 @@
To: Users
From: Bob Supnik
Subj: H316 Simulator Usage
Date: 01-Dec-2005
COPYRIGHT NOTICE
The following copyright notice applies to both the SIMH source and binary:
Original code published in 1993-2005, written by Robert M Supnik
Copyright (c) 1993-2005, Robert M Supnik
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Except as contained in this notice, the name of Robert M Supnik shall not be
used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from Robert M Supnik.
This memorandum documents the Honeywell 316/516 simulator.
1. Simulator Files
The H316 requires the following files:
sim/ scp.h
sim_console.h
sim_defs.h
sim_fio.h
sim_rev.h
sim_sock.h
sim_tape.h
sim_timer.h
sim_tmxr.h
scp.c
sim_console.c
sim_fio.c
sim_sock.c
sim_tape.c
sim_timer.c
sim_tmxr.c
sim/h316/ h316_defs.h
h316_cpu.c
h316_fhd.c
h316_lp.c
h316_mt.c
h316_dp.c
h316_stddev.c
h316_sys.c
2. H316/H516 Features
The Honeywell 316/516 simulator is configured as follows:
device simulates
name(s)
CPU H316/H516 CPU with 16/32KW memory
PTR 316/516-50 paper tape reader
PTP 316/516-52 paper tape punch
TTY 316/516-33 console terminal
CLK 316/516-12 real time clock
LPT 316/516 line printer
FHD 4400 fixed head disk
DP 4623/4653/4720 disk pack controller with eight drives
MT 4100 seven track magtape with four drives
The H316/H516 simulator implements several unique stop conditions:
- decode of an undefined instruction, and STOP_INST is et
- reference to an undefined I/O device, and STOP_DEV is set
- more than INDMAX indirect references are detected during
memory reference address decoding
- DMA/DMC direction does not agree with I/O device operation
- a write operation is initiated on a write locked magtape
unit (hangs the real system)
- a disk write overruns the specified record size (destroys
the rest of the track on the real system)
- a disk track has an illegal format
The H316/H516 loader is not implemented.
2.1 CPU
CPU options include choice of instruction set, memory size, DMC option,
and number of DMA channels.
SET CPU HSA high speed arithmetic instructions
SET CPU NOHSA no high speed arithmetic instructions
SET CPU 4K set memory size = 4K
SET CPU 8K set memory size = 8K
SET CPU 12K set memory size = 12K
SET CPU 16K set memory size = 16K
SET CPU 24K set memory size = 24K
SET CPU 32K set memory size = 32K
SET CPU DMC enable DMC option
SET CPU NODMC disable DMC option
SET CPU DMA=n set number of DMA channels to n (0-4)
If memory size is being reduced, and the memory being truncated contains
non-zero data, the simulator asks for confirmation. Data in the truncated
portion of memory is lost. Initial memory size is 32K. The HSA and DMC
options are enabled, and four DMA channels are configured.
The CPU includes special show commands to display the state of the DMA
channels:
SHOW CPU DMAn show DMA channel n
CPU registers include the visible state of the processor as well as the
control registers for the interrupt system.
name size comments
P 15 program counter
A 16 A register
B 16 B register
X 16 index register
SC 16 shift count
C 1 carry flag
EXT 1 extend flag
PME 1 previous mode extend flag
EXT_OFF 1 extend off pending flag
DP 1 double precision flag
SS1..4 1 sense switches 1..4
ION 1 interrupts enabled
INODEF 1 interrupts not deferred
INTREQ 16 interrupt requests
DEVRDY 16 device ready flags (read only)
DEVENB 16 device interrupt enable flags (read only)
CHREQ 20 DMA/DMC channel requests
DMAAD[0:3] 16 DMA channel current address, channels 1-4
DMAWC[0:3] 15 DMA channel word count, channels 1-4
DMAEOR[0:3] 1 DMA end of range flag, channels 1-4
STOP_INST 1 stop on undefined instruction
STOP_DEV 1 stop on undefined device
INDMAX 1 indirect address limit
PCQ[0:63] 15 PC prior to last JMP, JSB, or interrupt;
most recent PC change first
WRU 8 interrupt character
The CPU can maintain a history of the most recently executed instructions.
This is controlled by the SET CPU HISTORY and SHOW CPU HISTORY commands:
SET CPU HISTORY clear history buffer
SET CPU HISTORY=0 disable history
SET CPU HISTORY=n enable history, length = n
SHOW CPU HISTORY print CPU history
SHOW CPU HISTORY=n print first n entries of CPU history
The maximum length for the history is 65536 entries.
2.2 Programmed I/O Devices
2.2.1 316/516-50 Paper Tape Reader (PTR)
The paper tape reader (PTR) reads data from a disk file. The POS
register specifies the number of the next data item to be read.
Thus, by changing POS, the user can backspace or advance the reader.
The paper tape reader can bet set to operate in binary, ASCII, or
Unix ASCII mode:
sim> set ptr binary -- binary mode
sim> set ptr ascii -- ASCII mode
sim> set ptr uascii -- Unix ASCII mode
The mode can also be set by a switch setting in the attach command:
sim> att -b ptr <file> -- binary mode
sim> att -a ptr <file> -- ASCII mode
sim> att -u ptr <file> -- Unix ASCII mode
In ASCII or Unix ASCII mode, all non-zero characters have the high
order bit forced on. In Unix ASCII mode, newline is converted to
CR, and LF in inserted as the following character.
The paper tape reader supports the BOOT command. BOOT PTR copies the
absolute binary loader into memory and starts it running.
The paper tape reader implements these registers:
name size comments
BUF 8 last data item processed
INTREQ 1 device interrupt request
READY 1 device ready
ENABLE 1 device interrupts enabled
POS 32 position in the input or output file
TIME 24 time from I/O initiation to interrupt
STOP_IOE 1 stop on I/O error
Error handling is as follows:
error STOP_IOE processed as
not attached 1 report error and stop
0 out of tape
end of file 1 report error and stop
0 out of tape or paper
OS I/O error x report error and stop
2.2.2 316/516-52 Paper Tape Punch (PTP)
The paper tape punch (PTP) writes data to a disk file. The POS
register specifies the number of the next data item to be written.
Thus, by changing POS, the user can backspace or advance the punch.
The paper tape punch can bet set to operate in binary, ASCII, or
Unix ASCII mode:
sim> set ptp binary -- binary mode
sim> set ptp ascii -- ASCII mode
sim> set ptp uascii -- Unix ASCII mode
The mode can also be set by a switch setting in the attach command:
sim> att -b ptp <file> -- binary mode
sim> att -a ptp <file> -- ASCII mode
sim> att -u ptp <file> -- Unix ASCII mode
In ASCII or Unix ASCII mode, all characters are masked to 7b
before being written to the output file. In Unix ASCII mode, LF
is converted to newline, and CR is discarded.
The paper tape punch implements these registers:
name size comments
BUF 8 last data item processed
INTREQ 1 device interrupt request
READY 1 device ready
ENABLE 1 device interrupts enabled
POWER 1 device powered up
POS 32 position in the input or output file
TIME 24 time from I/O initiation to interrupt
PWRTIME 24 time from I/O request to power up
STOP_IOE 1 stop on I/O error
Error handling is as follows:
error STOP_IOE processed as
not attached 1 report error and stop
0 out of tape
OS I/O error x report error and stop
2.2.3 316/516-33 Console Teletype (TTY)
The console Teletype (TTY) consists of four separate units:
TTY0 keyboard
TTY1 printer
TTY2 paper tape reader
TTY3 paper tape punch
The keyboard and printer (TTY0, TTY1) can be set to one of four modes,
KSR, 7P, 7B, or 8B:
mode input characters output characters
KSR lower case converted lower case converted
to upper case, to upper case,
high-order bit set high-order bit cleared,
non-printing characters
suppressed
7P high-order bit cleared high-order bit cleared,
non-printing characters
suppressed
7B high-order bit cleared high-order bit cleared
8B no changes no changes
The default mode is KSR. The Teletype keyboard reads from the console
keyboard, and the printer writes to the simulator console window.
The paper tape reader (TTY2) can bet set to operate in binary, ASCII, or
Unix ASCII mode:
sim> set tty2 binary -- binary mode
sim> set tty2 ascii -- ASCII mode
sim> set tty2 uascii -- Unix ASCII mode
The mode can also be set by a switch setting in the attach command:
sim> att -b tty2 <file> -- binary mode
sim> att -a tty2 <file> -- ASCII mode
sim> att -u tty2 <file> -- Unix ASCII mode
In ASCII or Unix ASCII mode, all non-zero characters have the high
order bit forced on. In Unix ASCII mode, newline is converted to
CR, and LF in inserted as the following character.
The paper tape reader is started by program output of XON or by
the command SET TTY2 START. The paper tape reader is stopped by
reader input of XOFF or by the command SET TTY2 STOP.
The paper tape punch (TTY3) can bet set to operate in binary, ASCII, or
Unix ASCII mode:
sim> set tty3 binary -- binary mode
sim> set tty3 ascii -- ASCII mode
sim> set tty3 uascii -- Unix ASCII mode
The mode can also be set by a switch setting in the attach command:
sim> att -b tty3 <file> -- binary mode
sim> att -a tty3 <file> -- ASCII mode
sim> att -u tty3 <file> -- Unix ASCII mode
In ASCII or Unix ASCII mode, all characters are masked to 7b
before being written to the output file. In Unix ASCII mode, LF
is converted to newline, and CR is discarded.
The paper tape punch is started by program output of TAPE or by
the command SET TTY3 START. The paper tape punch is stopped by
program output of XOFF or by the command SET TTY3 STOP.
It implements these registers:
name size comments
BUF 8 last data item processed
MODE 1 read/write mode
INTREQ 1 device interrupt request
READY 1 device ready
ENABLE 1 device interrupts enabled
KPOS 32 number of keyboard characters input
KTIME 24 keyboard polling interval
TPOS 32 number of printer characters output
TTIME 24 time from I/O initiation to interrupt
RPOS 32 current reader character position
PPOS 32 current punch character position
2.2.4 316/516-12 Real Time Clock (CLK)
The real time clock (CLK) frequency can be adjusted as follows:
SET CLK 60HZ set frequency to 60Hz
SET CLK 50HZ set frequency to 50Hz
The default is 60Hz.
The clock implements these registers:
name size comments
INTREQ 1 device interrupt request
READY 1 device ready
ENABLE 1 device interrupts enabled
TIME 24 clock interval
The real-time clock autocalibrates; the clock interval is adjusted up or
down so that the clock tracks actual elapsed time.
2.3 316/516 Line Printer (LPT)
The line printer (LPT) writes data to a disk file. The POS register
specifies the number of the next data item to be written. Thus,
by changing POS, the user can backspace or advance the printer.
The line printer can be connected to the IO bus, a DMC channel, or
a DMA channel:
SET LPT IOBUS connect to IO bus
SET LPT DMC=n connect to DMC channel n (1-16)
SET LPT DMA=n connect to DMA channel n (1-4)
By default, the line printer is connected to the IO bus.
The line printer implements these registers:
name size comments
WDPOS 6 word position in current scan
DRPOS 6 drum position
CRPOS 1 carriage position
PRDN 1 print done flag
RDY 1 ready flag
EOR 1 (DMA/DMC) end of range flag
DMA 1 transfer using DMA/DMC
INTREQ 1 device interrupt request
ENABLE 1 device interrupt enable
SVCST 2 service state
SVCCH 2 service channel
BUF 8 buffer
POS 32 number of characters output
XTIME 24 delay between transfers
ETIME 24 delay at end of scan
PTIME 24 delay for shuttle/line advance
STOP_IOE 1 stop on I/O error
Error handling is as follows:
error STOP_IOE processed as
not attached 1 report error and stop
0 out of paper
OS I/O error x report error and stop
2.4 4400 Fixed Head Disk (FHD)
Fixed head disk options include the ability to set the number of
surfaces to a fixed value between 1 and 16, or to autosize the number
of surfaces from the attached file:
SET FHD 1S one surface (98K)
SET FHD 2S two platters (196K)
:
SET FHD 16S sixteen surfaces (1568K)
SET FHD AUTOSIZE autosized on attach
The default is one surface.
The fixed head disk can be connected to the IO bus, a DMC channel, or
a DMA channel:
SET FHD IOBUS connect to IO bus
SET FHD DMC=n connect to DMC channel n (1-16)
SET FHD DMA=n connect to DMA channel n (1-4)
By default, the fixed head disk is connected to the IO bus.
The fixed head disk implements these registers:
name size comments
CW1 16 control word 1 (read write, surface, track)
CW2 16 control word 2 (character address)
BUF 16 data buffer
BUSY 1 controller busy flag
RDY 1 transfer ready flag
DTE 1 data transfer error flag
ACE 1 access error flag
EOR 1 (DMA/DMC) end of range
DMA 1 transfer using DMA/DMC
CSUM 1 transfer parity checksum
INTREQ 1 device interrupt request
ENABLE 1 device interrupt enable
TIME 24 delay between words
STOP_IOE 1 stop on I/O error
The fixed head disk does not support the BOOT command.
Error handling is as follows:
error STOP_IOE processed as
not attached 1 report error and stop
0 disk not ready
Fixed head disk data files are buffered in memory; therefore, end of file
and OS I/O errors cannot occur.
2.5 4100 7-track Magnetic Tape (MT)
Magnetic tape options include the ability to make units write enabled or
or write locked.
SET MTn LOCKED set unit n write locked
SET MTn WRITEENABLED set unit n write enabled
Units can also be set ENABLED or DISABLED.
The magtape controller can be connected to the IO bus, a DMC channel, or
a DMA channel:
SET MT IOBUS connect to IO bus
SET MT DMC=n connect to DMC channel n (1-16)
SET MT DMA=n connect to DMA channel n (1-4)
By default, the magtape controller is connected to the IO bus.
The magnetic tape controller implements these registers:
name size comments
BUF 16 data buffer
USEL 2 unit select
BUSY 1 controller busy flag
RDY 1 transfer ready flag
ERR 1 error flag
EOF 1 end of file flag
EOR 1 (DMA/DMC) end of range
DMA 1 transfer using DMA/DMC
MDIRQ 1 motion done interrupt request
INTREQ 1 device interrupt request
ENABLE 1 device interrupt enable
DBUF[0:65535] 8 transfer buffer
BPTR 17 transfer buffer pointer
BMAX 17 transfer size (reads)
CTIME 24 start/stop time
XTIME 24 delay between words
POS[0:3] 32 position, units 0-3
STOP_IOE 1 stop on I/O error
Error handling is as follows:
error processed as
not attached tape not ready; if STOP_IOE, stop
end of file bad tape
OS I/O error parity error; if STOP_IOE, stop
2.6 4623/4651/4720 Disk Packs (DP)
The disk controller can be configured as a 4623, supporting 10 surface
disk packs; a 4651, supporting 2 surface disk packs; or a 4720, supporting
20 surface disk packs:
SET DP 4623 controller is 4623
SET DP 4651 controller is 4651
SET DP 4720 controller is 4720
The default is 4651. All disk packs on the controller must be of the
same type. Units can be set ENABLED or DISABLED, and WRITEENABLED or
write LOCKED.
The disk pack controller can be connected to a DMC channel or a DMA
channel; it cannot be connected to the IO bus:
SET DP DMC=n connect to DMC channel n (1-16)
SET DP DMA=n connect to DMA channel n (1-4)
The disk pack controller supports variable track formatting. Each track
can contain between 1 and 103 records, with a minimum size of 1 word and
a maximum size of 1893 words. Record addresses are unconstrained. The
simulator provides a command to perform a simple, fixed record size format
of a new disk:
SET DPn FORMAT=k format unit n with k words per record
SET -R DPn FORMAT=k format unit n with k records per track
Record addresses can either be geometric (cylinder/track/sector) or simple
sequential starting from 0:
SET DPn FORMAT=k format with geometric record addresses
SET -S DPn FORMAT=k format with sequential record addresses
Geometric address have the cylinder number in bits<1:8>, the head number in
bits<9:13>, and the sector number in bits <14:16>.
A summary of the current format, and its validity, can be obtained with
the command:
SHOW DPn FORMAT display format of unit n
To accomodate the variable formatting, each track is allocated 2048 words
in the data file. A record consists of a three word header, the data, and
a five word trailer:
word 0 record length in words, not including header/trailer
word 1 record address
word 2 number of extension words used (0-4)
word 3 start of data record
word 3+n-1 end of data record
word 3+n..7+n record trailer: up to four extension words,
plus checksum
A record can "grow" by up to four words without disrupting the track formatting;
writing more than four extra words destroys the formatting of the rest of the
track and causes a simulator error.
The disk pack controller implements these registers:
name size comments
STA 16 status
BUF 16 data buffer
FNC 4 controller function
CW1 16 command word 1
CW2 16 command word 2
CSUM 16 record checksum
BUSY 1 controller busy
RDY 1 transfer ready
EOR 1 (DMA/DMC) end of range
DEFINT 1 seek deferred interrupt pending
INTREQ 1 interrupt request
ENABLE 1 interrupt enable
TBUF[0:2047] 16 track buffer
RPTR 11 pointer to start of record in track buffer
WPTR 11 pointer to current word in record
BCTR 15 bit counter for formatting
STIME 24 seek time, per cylinder
XTIME 24 transfer time, per word
BTIME 24 controller busy time
Error handling is as follows:
error processed as
not attached pack off line; if STOP_IOE, stop
end of file ignored
OS I/O error data error; if STOP_IOE, stop
2.7 Symbolic Display and Input
The H316/H516 simulator implements symbolic display and input. Display is
controlled by command line switches:
-a display as ASCII character
-c display as two character string
-m display instruction mnemonics
Input parsing is controlled by the first character typed in or by command
line switches:
' or -a ASCII character
" or -c two character sixbit string
alphabetic instruction mnemonic
numeric octal number
Instruction input uses standard H316/H516 assembler syntax. There are six
instruction classes: memory reference, I/O, control, shift, skip, and
operate.
Memory reference instructions have the format
memref{*} {C/Z} address{,1}
where * signifies indirect, C a current sector reference, Z a sector zero
reference, and 1 indexed. The address is an octal number in the range 0 -
077777; if C or Z is specified, the address is a page offset in the range
0 - 0777. Normally, C is not needed; the simulator figures out from the
address what mode to use. However, when referencing memory outside the CPU,
there is no valid PC, and C must be used to specify current sector addressing.
I/O instructions have the format
io pulse+device
The pulse+device is an octal number in the range 0 - 01777.
Control and operate instructions consist of a single opcode
opcode
Shift instructions have the format
shift n
where n is an octal number in the range 0-77.
Skip instructions have the format
sub-op sub-op sub-op...
The simulator checks that the combination of sub-opcodes is legal.

View file

@ -1,6 +1,6 @@
/* h316_fhd.c: H316/516 fixed head simulator /* h316_fhd.c: H316/516 fixed head simulator
Copyright (c) 2003-2005, Robert M. Supnik Copyright (c) 2003-2006, Robert M. Supnik
Permission is hereby granted, free of charge, to any person obtaining a Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"), copy of this software and associated documentation files (the "Software"),
@ -25,6 +25,7 @@
fhd 516-4400 fixed head disk fhd 516-4400 fixed head disk
15-May-06 RMS Fixed bug in autosize attach (reported by David Gesswein)
04-Jan-04 RMS Changed sim_fsize calling sequence 04-Jan-04 RMS Changed sim_fsize calling sequence
These head-per-track devices are buffered in memory, to minimize overhead. These head-per-track devices are buffered in memory, to minimize overhead.
@ -63,7 +64,7 @@
#define CW2_GETCA(x) (((x) >> CW2_V_CA) & CW2_M_CA) #define CW2_GETCA(x) (((x) >> CW2_V_CA) & CW2_M_CA)
#define GET_POS(x) ((int) fmod (sim_gtime() / ((double) (x)), \ #define GET_POS(x) ((int) fmod (sim_gtime() / ((double) (x)), \
((double) FH_NUMWD))) ((double) FH_NUMWD)))
/* OTA states */ /* OTA states */
@ -93,7 +94,6 @@ int32 fhdio (int32 inst, int32 fnc, int32 dat, int32 dev);
t_stat fhd_svc (UNIT *uptr); t_stat fhd_svc (UNIT *uptr);
t_stat fhd_reset (DEVICE *dptr); t_stat fhd_reset (DEVICE *dptr);
t_stat fhd_attach (UNIT *uptr, char *cptr); t_stat fhd_attach (UNIT *uptr, char *cptr);
t_stat fhd_boot (int32 unitno, DEVICE *dptr);
t_stat fhd_set_size (UNIT *uptr, int32 val, char *cptr, void *desc); t_stat fhd_set_size (UNIT *uptr, int32 val, char *cptr, void *desc);
void fhd_go (uint32 dma); void fhd_go (uint32 dma);
void fhd_go1 (uint32 dat); void fhd_go1 (uint32 dat);
@ -433,18 +433,15 @@ t_stat fhd_attach (UNIT *uptr, char *cptr)
{ {
uint32 sz, sf; uint32 sz, sf;
uint32 ds_bytes = FH_WDPSF * sizeof (int16); uint32 ds_bytes = FH_WDPSF * sizeof (int16);
t_stat r;
r = attach_unit (uptr, cptr); if ((uptr->flags & UNIT_AUTO) && (sz = sim_fsize_name (cptr))) {
if (r != SCPE_OK) return r;
if ((uptr->flags & UNIT_AUTO) && (sz = sim_fsize (uptr->fileref))) {
sf = (sz + ds_bytes - 1) / ds_bytes; sf = (sz + ds_bytes - 1) / ds_bytes;
if (sf >= FH_NUMSF) sf = FH_NUMSF - 1; if (sf >= FH_NUMSF) sf = FH_NUMSF - 1;
uptr->flags = (uptr->flags & ~UNIT_SF) | uptr->flags = (uptr->flags & ~UNIT_SF) |
(sf << UNIT_V_SF); (sf << UNIT_V_SF);
} }
uptr->capac = UNIT_GETSF (uptr->flags) * FH_WDPSF; uptr->capac = UNIT_GETSF (uptr->flags) * FH_WDPSF;
return SCPE_OK; return attach_unit (uptr, cptr);
} }
/* Set size routine */ /* Set size routine */

View file

@ -1,6 +1,6 @@
/* h316_lp.c: Honeywell 316/516 line printer /* h316_lp.c: Honeywell 316/516 line printer
Copyright (c) 1999-2005, Robert M. Supnik Copyright (c) 1999-2006, Robert M. Supnik
Permission is hereby granted, free of charge, to any person obtaining a Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"), copy of this software and associated documentation files (the "Software"),
@ -25,6 +25,7 @@
lpt line printer lpt line printer
03-Apr-06 RMS Fixed bug in blanks backscanning (from Theo Engel)
01-Dec-04 RMS Fixed bug in DMA/DMC support 01-Dec-04 RMS Fixed bug in DMA/DMC support
24-Oct-03 RMS Added DMA/DMC support 24-Oct-03 RMS Added DMA/DMC support
25-Apr-03 RMS Revised for extended file support 25-Apr-03 RMS Revised for extended file support
@ -298,7 +299,7 @@ if (lpt_svcst & LPT_SVCSH) { /* shuttling */
} }
if (lpt_svcst & LPT_SVCPA) { /* paper advance */ if (lpt_svcst & LPT_SVCPA) { /* paper advance */
SET_INT (INT_LPT); /* interrupt */ SET_INT (INT_LPT); /* interrupt */
for (i = LPT_WIDTH - 1; i >= 0; i++) { for (i = LPT_WIDTH - 1; i >= 0; i--) { /* backscan for blanks */
if (lpt_buf[i] != ' ') break; if (lpt_buf[i] != ' ') break;
} }
lpt_buf[i + 1] = 0; lpt_buf[i + 1] = 0;

View file

@ -1,6 +1,6 @@
/* h316_mt.c: H316/516 magnetic tape simulator /* h316_mt.c: H316/516 magnetic tape simulator
Copyright (c) 2003-2005, Robert M. Supnik Copyright (c) 2003-2006, Robert M. Supnik
Permission is hereby granted, free of charge, to any person obtaining a Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"), copy of this software and associated documentation files (the "Software"),
@ -25,6 +25,7 @@
mt 516-4100 seven track magnetic tape mt 516-4100 seven track magnetic tape
16-Feb-06 RMS Added tape capacity checking
26-Aug-05 RMS Revised to use API for write lock check 26-Aug-05 RMS Revised to use API for write lock check
08-Feb-05 RMS Fixed error reporting from OCP (found by Philipp Hachtmann) 08-Feb-05 RMS Fixed error reporting from OCP (found by Philipp Hachtmann)
01-Dec-04 RMS Fixed bug in DMA/DMC support 01-Dec-04 RMS Fixed bug in DMA/DMC support
@ -154,6 +155,8 @@ MTAB mt_mod[] = {
{ MTUF_WLK, MTUF_WLK, "write locked", "LOCKED", NULL }, { MTUF_WLK, MTUF_WLK, "write locked", "LOCKED", NULL },
{ MTAB_XTD|MTAB_VUN, 0, "FORMAT", "FORMAT", { MTAB_XTD|MTAB_VUN, 0, "FORMAT", "FORMAT",
&sim_tape_set_fmt, &sim_tape_show_fmt, NULL }, &sim_tape_set_fmt, &sim_tape_show_fmt, NULL },
{ MTAB_XTD|MTAB_VUN, 0, "CAPACITY", "CAPACITY",
&sim_tape_set_capac, &sim_tape_show_capac, NULL },
{ MTAB_XTD|MTAB_VDV, 0, NULL, "IOBUS", { MTAB_XTD|MTAB_VDV, 0, NULL, "IOBUS",
&io_set_iobus, NULL, NULL }, &io_set_iobus, NULL, NULL },
{ MTAB_XTD|MTAB_VDV, 0, NULL, "DMC", { MTAB_XTD|MTAB_VDV, 0, NULL, "DMC",
@ -177,7 +180,7 @@ DEVICE mt_dev = {
int32 mtio (int32 inst, int32 fnc, int32 dat, int32 dev) int32 mtio (int32 inst, int32 fnc, int32 dat, int32 dev)
{ {
uint32 u = dev & 03; uint32 i, u = dev & 03;
UNIT *uptr = mt_dev.units + u; UNIT *uptr = mt_dev.units + u;
static uint8 wrt_fnc[16] = { /* >0 = wr, 1 = chan op */ static uint8 wrt_fnc[16] = { /* >0 = wr, 1 = chan op */
0, 0, 0, 0, 1, 1, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0 0, 0, 0, 0, 1, 1, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0
@ -222,6 +225,8 @@ switch (inst) { /* case on opcode */
uptr->FNC = fnc; uptr->FNC = fnc;
uptr->UST = 0; uptr->UST = 0;
mt_busy = 1; mt_busy = 1;
for (i = 0; i < MT_NUMDR; i++) /* clear all EOT flags */
mt_unit[i].UST = mt_unit[i].UST & ~STA_EOT;
sim_activate (uptr, mt_ctime); /* schedule */ sim_activate (uptr, mt_ctime); /* schedule */
break; break;
} }
@ -319,6 +324,7 @@ t_stat mt_svc (UNIT *uptr)
int32 ch = mt_dib.chan - 1; /* DMA/DMC ch */ int32 ch = mt_dib.chan - 1; /* DMA/DMC ch */
uint32 i, c1, c2, c3; uint32 i, c1, c2, c3;
t_mtrlnt tbc; t_mtrlnt tbc;
t_bool passed_eot;
t_stat st, r = SCPE_OK; t_stat st, r = SCPE_OK;
if ((uptr->flags & UNIT_ATT) == 0) { /* offline? */ if ((uptr->flags & UNIT_ATT) == 0) { /* offline? */
@ -328,6 +334,7 @@ if ((uptr->flags & UNIT_ATT) == 0) { /* offline? */
return IORETURN (mt_stopioe, SCPE_UNATT); return IORETURN (mt_stopioe, SCPE_UNATT);
} }
passed_eot = sim_tape_eot (uptr); /* passed EOT? */
switch (uptr->FNC) { /* case on function */ switch (uptr->FNC) { /* case on function */
case FNC_REW: /* rewind (initial) */ case FNC_REW: /* rewind (initial) */
@ -442,6 +449,8 @@ switch (uptr->FNC) { /* case on function */
/* End of command, process error or schedule end of motion */ /* End of command, process error or schedule end of motion */
if (!passed_eot && sim_tape_eot (uptr)) /* just passed EOT? */
uptr->UST = uptr->UST | STA_EOT;
if (r != SCPE_OK) { if (r != SCPE_OK) {
uptr->FNC = FNC_NOP; /* nop function */ uptr->FNC = FNC_NOP; /* nop function */
mt_busy = 0; /* not busy */ mt_busy = 0; /* not busy */

View file

@ -1,6 +1,6 @@
/* h316_stddev.c: Honeywell 316/516 standard devices /* h316_stddev.c: Honeywell 316/516 standard devices
Copyright (c) 1999-2005, Robert M. Supnik Copyright (c) 1999-2006, Robert M. Supnik
Permission is hereby granted, free of charge, to any person obtaining a Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"), copy of this software and associated documentation files (the "Software"),
@ -28,6 +28,7 @@
tty 316/516-33 teleprinter tty 316/516-33 teleprinter
clk/options 316/516-12 real time clocks/internal options clk/options 316/516-12 real time clocks/internal options
03-Apr-06 RMS Fixed bugs in punch state handling (from Theo Engel)
22-Nov-05 RMS Revised for new terminal processing routines 22-Nov-05 RMS Revised for new terminal processing routines
05-Feb-05 RMS Fixed bug in OCP '0001 (found by Philipp Hachtmann) 05-Feb-05 RMS Fixed bug in OCP '0001 (found by Philipp Hachtmann)
31-Jan-05 RMS Fixed bug in TTY print (found by Philipp Hachtmann) 31-Jan-05 RMS Fixed bug in TTY print (found by Philipp Hachtmann)
@ -608,7 +609,7 @@ else if ((ruptr->flags & UNIT_ATT) && /* TTR attached */
(ruptr->STA & RUNNING)) { /* and running? */ (ruptr->STA & RUNNING)) { /* and running? */
if (ruptr->STA & LF_PEND) { /* lf pending? */ if (ruptr->STA & LF_PEND) { /* lf pending? */
c = 0212; /* char is lf */ c = 0212; /* char is lf */
ruptr->STA &= LF_PEND; /* clear flag */ ruptr->STA &= ~LF_PEND; /* clear flag */
} }
else { /* normal read */ else { /* normal read */
if ((c = getc (ruptr->fileref)) == EOF) { /* read byte */ if ((c = getc (ruptr->fileref)) == EOF) { /* read byte */
@ -665,7 +666,7 @@ if (ttp_tape_rcvd != 0) { /* prev = tape? */
else if (c7b == TAPE) ttp_tape_rcvd = 2; /* char = TAPE? */ else if (c7b == TAPE) ttp_tape_rcvd = 2; /* char = TAPE? */
if (ttp_xoff_rcvd != 0) { /* prev = XOFF? */ if (ttp_xoff_rcvd != 0) { /* prev = XOFF? */
ttp_xoff_rcvd--; /* decrement state */ ttp_xoff_rcvd--; /* decrement state */
if (ttp_xoff_rcvd == 0) puptr->STA &= RUNNING; /* stop after delay */ if (ttp_xoff_rcvd == 0) puptr->STA &= ~RUNNING; /* stop after delay */
} }
else if (c7b == XOFF) ttp_xoff_rcvd = 2; /* char = XOFF? */ else if (c7b == XOFF) ttp_xoff_rcvd = 2; /* char = XOFF? */
if ((c7b == XON) && (ruptr->flags & UNIT_ATT)) { /* char = XON? */ if ((c7b == XON) && (ruptr->flags & UNIT_ATT)) { /* char = XON? */

File diff suppressed because it is too large Load diff

View file

@ -1,6 +1,6 @@
/* hp2100_ms.c: HP 2100 13181A/13183A magnetic tape simulator /* hp2100_ms.c: HP 2100 13181A/13183A magnetic tape simulator
Copyright (c) 1993-2005, Robert M. Supnik Copyright (c) 1993-2006, Robert M. Supnik
Permission is hereby granted, free of charge, to any person obtaining a Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"), copy of this software and associated documentation files (the "Software"),
@ -26,6 +26,7 @@
ms 13181A 7970B 800bpi nine track magnetic tape ms 13181A 7970B 800bpi nine track magnetic tape
13183A 7970E 1600bpi nine track magnetic tape 13183A 7970E 1600bpi nine track magnetic tape
16-Feb-06 RMS Revised for new EOT test
22-Jul-05 RMS Fixed compiler warning on Solaris (from Doug Glyn) 22-Jul-05 RMS Fixed compiler warning on Solaris (from Doug Glyn)
01-Mar-05 JDB Added SET OFFLINE; rewind/offline now does not detach 01-Mar-05 JDB Added SET OFFLINE; rewind/offline now does not detach
07-Oct-04 JDB Fixed enable/disable from either device 07-Oct-04 JDB Fixed enable/disable from either device
@ -445,8 +446,8 @@ switch (inst) { /* case on opcode */
dat = dat | STA_TBSY; dat = dat | STA_TBSY;
if (sim_tape_wrp (uptr)) /* write prot? */ if (sim_tape_wrp (uptr)) /* write prot? */
dat = dat | STA_WLK; dat = dat | STA_WLK;
if (uptr->REEL && uptr->capac = (TCAP << uptr->REEL) << ms_ctype;
sim_tape_eot (uptr, (TCAP << uptr->REEL) << ms_ctype)) if (sim_tape_eot (uptr))
dat = dat | STA_EOT; dat = dat | STA_EOT;
} }
else dat = dat | STA_TBSY | STA_LOCAL; else dat = dat | STA_TBSY | STA_LOCAL;
@ -529,7 +530,7 @@ return dat;
t_stat msc_svc (UNIT *uptr) t_stat msc_svc (UNIT *uptr)
{ {
int32 devc, devd, unum, cap; int32 devc, devd, unum;
t_mtrlnt tbc; t_mtrlnt tbc;
t_stat st, r = SCPE_OK; t_stat st, r = SCPE_OK;
@ -588,10 +589,9 @@ switch (uptr->FNC) { /* case on function */
break; break;
case FNC_FSF: /* space fwd file */ case FNC_FSF: /* space fwd file */
cap = (TCAP << uptr->REEL) << ms_ctype; uptr->capac = (TCAP << uptr->REEL) << ms_ctype;
while ((st = sim_tape_sprecf (uptr, &tbc)) == MTSE_OK) { while ((st = sim_tape_sprecf (uptr, &tbc)) == MTSE_OK) {
if (uptr->REEL && sim_tape_eot (uptr, cap)) if (sim_tape_eot (uptr)) break; /* EOT stops */
break; /* EOT stops */
} }
r = ms_map_err (uptr, st); /* map error */ r = ms_map_err (uptr, st); /* map error */
break; break;

View file

@ -1,6 +1,6 @@
/* i1401_cpu.c: IBM 1401 CPU simulator /* i1401_cpu.c: IBM 1401 CPU simulator
Copyright (c) 1993-2005, Robert M. Supnik Copyright (c) 1993-2006, Robert M. Supnik
Permission is hereby granted, free of charge, to any person obtaining a Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"), copy of this software and associated documentation files (the "Software"),
@ -23,6 +23,8 @@
used in advertising or otherwise to promote the sale, use or other dealings used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from Robert M Supnik. in this Software without prior written authorization from Robert M Supnik.
22-May-06 RMS Fixed format error in CPU history (found by Peter Schorn)
06-Mar-06 RMS Fixed bug in divide (found by Van Snyder)
22-Sep-05 RMS Fixed declarations (from Sterling Garwood) 22-Sep-05 RMS Fixed declarations (from Sterling Garwood)
01-Sep-05 RMS Removed error stops in MCE 01-Sep-05 RMS Removed error stops in MCE
16-Aug-05 RMS Fixed C++ declaration and cast problems 16-Aug-05 RMS Fixed C++ declaration and cast problems
@ -1333,7 +1335,8 @@ CHECK_LENGTH:
*/ */
case OP_DIV: case OP_DIV:
asave = AS; ahigh = -1; asave = AS;
ahigh = -1;
do { do {
a = M[AS]; /* get dvr char */ a = M[AS]; /* get dvr char */
if ((a & CHAR) != BCD_ZERO) ahigh = AS; /* mark non-zero */ if ((a & CHAR) != BCD_ZERO) ahigh = AS; /* mark non-zero */
@ -1379,9 +1382,11 @@ CHECK_LENGTH:
t = div_sub (asave, bsave, ahigh); /* subtract */ t = div_sub (asave, bsave, ahigh); /* subtract */
quo++; /* incr quo digit */ quo++; /* incr quo digit */
} while (t == 0); /* until borrow */ } while (t == 0); /* until borrow */
div_add (asave, bsave, ahigh); quo--; /* restore */ div_add (asave, bsave, ahigh); /* restore */
quo--;
M[qs] = (M[qs] & WM) | sum_table[quo]; /* store quo digit */ M[qs] = (M[qs] & WM) | sum_table[quo]; /* store quo digit */
bsave++; qs++; /* adv divd, quo */ bsave++; /* adv divd, quo */
qs++;
} while ((b & ZONE) == 0); /* until B sign */ } while ((b & ZONE) == 0); /* until B sign */
if (reason) break; /* address err? */ if (reason) break; /* address err? */
@ -1583,7 +1588,8 @@ int32 a, b, c, r;
c = 0; /* init borrow */ c = 0; /* init borrow */
do { do {
a = M[ap]; b = M[bp]; /* get operands */ a = M[ap]; /* get operands */
b = M[bp];
r = bcd_to_bin[b & DIGIT] - /* a - b - borrow */ r = bcd_to_bin[b & DIGIT] - /* a - b - borrow */
bcd_to_bin[a & DIGIT] - c; bcd_to_bin[a & DIGIT] - c;
c = (r < 0); /* set borrow out */ c = (r < 0); /* set borrow out */
@ -1592,7 +1598,7 @@ do {
bp--; bp--;
} while (ap >= aend); } while (ap >= aend);
b = M[bp] & CHAR; /* borrow position */ b = M[bp] & CHAR; /* borrow position */
if (b != BCD_ZERO) { /* non-zero? */ if (b && (b != BCD_ZERO)) { /* non-zero? */
r = bcd_to_bin[b & DIGIT] - c; /* subtract borrow */ r = bcd_to_bin[b & DIGIT] - c; /* subtract borrow */
M[bp] = sum_table[r]; /* store result */ M[bp] = sum_table[r]; /* store result */
return 0; /* subtract worked */ return 0; /* subtract worked */
@ -1772,7 +1778,7 @@ for (k = 0; k < lnt; k++) { /* print specified */
if ((fprint_sym (st, h->is, sim_eval, &cpu_unit, SWMASK ('M'))) > 0) { if ((fprint_sym (st, h->is, sim_eval, &cpu_unit, SWMASK ('M'))) > 0) {
fprintf (st, "(undefined)"); fprintf (st, "(undefined)");
for (i = 0; i < h->ilnt; i++) for (i = 0; i < h->ilnt; i++)
fprintf (st, "% 02o", h->inst[i]); fprintf (st, " %02o", h->inst[i]);
} }
fputc ('\n', st); /* end line */ fputc ('\n', st); /* end line */
} /* end else instruction */ } /* end else instruction */

View file

@ -1,579 +0,0 @@
To: Users
From: Bob Supnik
Subj: IBM 1401 Simulator Usage
Date: 01-Nov-05
COPYRIGHT NOTICE
The following copyright notice applies to both the SIMH source and binary:
Original code published in 1993-2005, written by Robert M Supnik
Copyright (c) 1993-2005, Robert M Supnik
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Except as contained in this notice, the name of Robert M Supnik shall not be
used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from Robert M Supnik.
This memorandum documents the IBM 1401 simulator.
1. Simulator Files
sim/ scp.h
sim_console.h
sim_defs.h
sim_fio.h
sim_rev.h
sim_sock.h
sim_tape.h
sim_timer.h
sim_tmxr.h
scp.c
sim_console.c
sim_fio.c
sim_sock.c
sim_tape.c
sim_timer.c
sim_tmxr.c
sim/i1401/ i1401_defs.h
i1401_dat.h
i1401_cpu.c
i1401_cd.c
i1401_iq.c
i1401_lp.c
i1401_dp.c
i1401_mt.c
i1401_sys.c
2. IBM 1401 Features
The IBM 1401 simulator is configured as follows:
device simulates
name(s)
CPU IBM 1401 CPU with 16K of memory
CDR,CDP IBM 1402 card reader/punch
LPT IBM 1403 line printer
INQ IBM 1407 inquiry terminal
DP IBM 1311 disk pack with five drives
MT IBM 729 7-track magnetic tape controller with six drives
The IBM 1401 simulator implements many unique stop conditions. On almost
any kind of error the simulator stops:
unimplemented opcode
reference to non-existent memory
reference to non-existent device
no word mark under opcode
invalid A address
invalid B address
invalid instruction length
invalid modifier character
invalid branch address
invalid magtape unit number
invalid magtape record length
write to locked magtape drive
skip to unpunched carriage control tape channel
card reader hopper empty
address register wrap-around
I/O check with I/O stop switch set
invalid disk drive
invalid disk sector address
invalid disk sector count
invalid disk address compare
The LOAD command is used to load a line printer carriage-control tape.
The DUMP command is not implemented.
2.1 CPU
The CPU options include a number of special features and the size of main
memory. Note that the Modify Address special feature is always included
when memory size is greater than 4K.
SET CPU XSA enable advanced programming special feature
SET CPU NOXSA disable advanced programming
SET CPU HLE enable high/low/equal special feature
SET CPU NOHLE disable high/low/equal
SET CPU BBE enable branch on bit equal special feature
SET CPU NOBBE disable branch on bit equal
SET CPU MR enable move record special feature
SET CPU NOMR disable move record
SET CPU EPE enable extended print edit special feature
SET CPU NOEPE disable extended print edit
SET CPU MDV enable multiply/divide special feature
SET CPU NOMDV disable multiply/divide
SET CPU 4K set memory size = 4K
SET CPU 8K set memory size = 8K
SET CPU 12K set memory size = 12K
SET CPU 16K set memory size = 16K
If memory size is being reduced, and the memory being truncated contains
non-zero data, the simulator asks for confirmation. Data in the truncated
portion of memory is lost. Initially, memory size is 16K, and all special
features are enabled.
Memory is implemented as 7 bit BCD characters, as follows:
6 5 4 3 2 1 0
word B bit A bit 8 4 2 1
mark <-- zone --> <-------- digit -------->
In BCD, the decimal digits 0-9 are (octal) values 012, 001, 002, 003, 004,
005, 006, 007, 010, 011, respectively. Signs are encoded in the zone bits,
with 00, 01, and 11 being positive, and 10 being negative.
CPU registers include the visible state of the processor. The 1401 has no
interrupt system.
name size comments
IS 14 instruction storage address register (PC)
AS 14 A storage address register
BS 14 B storage address register
ASERR 1 AS invalid flag
BSERR 1 BS invalid flag
SSA 1 sense switch A
SSB 1 sense switch B
SSC 1 sense switch C
SSD 1 sense switch D
SSE 1 sense switch E
SSF 1 sense switch F
SSG 1 sense switch G
EQU 1 equal compare indicator
UNEQ 1 unequal compare indicator
HIGH 1 high compare indicator
LOW 1 low compare indicator
OVF 1 overflow indicator
IOCHK 1 I/O check switch
PRCHK 1 process check switch
ISQ[0:63] 14 IS prior to last branch;
most recent IS change first
WRU 8 interrupt character
The CPU can maintain a history of the most recently executed instructions.
This is controlled by the SET CPU HISTORY and SHOW CPU HISTORY commands:
SET CPU HISTORY clear history buffer
SET CPU HISTORY=0 disable history
SET CPU HISTORY=n enable history, length = n
SHOW CPU HISTORY print CPU history
SHOW CPU HISTORY=n print first n entries of CPU history
The maximum length for the history is 65536 entries.
The original character encoding used by the 1401 simulator was revised to be
compatible with the coding used by Paul Pierce's 709X and 1401 simulators.
The user can select between the original (old) and compatible (new) encodings,
as follows:
SET CPU OLDCONVERSIONS use original character encoding
SET CPU NEWCONVERSIONS use compatible character encoding
NEWCONVERSIONS is the default.
2.2 1402 Card Reader/Punch (CDR, CDP, STKR)
The IBM 1402 card/reader punch is simulated as three independent devices:
the card reader (CDR), the card punch (CDP), and the reader and punch
stackers (STKR). STRK units 0, 1, 2, and 4 correspond to the reader
normal stacker, reader stacker 1, shared stacker 2/8, and punch stacker
4, respectively.
Card punch and stacker units support both the business (1403 print chain
A) and Fortran (1403 H chain) character sets:
SET CDP BUSINESS business character set
SET CDP FORTRAN Fortran character set
The business character set is the default.
The card reader supports the BOOT command. BOOT CDR reads a card image
into locations 1-80, sets a word mark under location 1, clears storage,
and then transfers control to location 1.
The card reader reads data from disk files, while the punch and stackers
write data to disk files. Cards are simulated as ASCII text lines with
terminating newlines; column binary is not supported. For each unit,
the POS register specifies the number of the next data item to be read or
written. Thus, by changing POS, the user can backspace or advance these
devices.
The card reader registers are:
name size comments
LAST 1 last card indicator
ERR 1 error indicator
S1 1 stacker 1 select flag
S2 1 stacker 2 select flag
POS 32 position
TIME 24 delay window for stacker select
BUF[0:79] 8 reader buffer
The card punch registers are:
ERR 1 error indicator
S4 1 stacker 4 select flag
S8 1 stacker 8 select flag
The stacker registers are:
POS0 32 position, normal reader stack
POS1 32 position, reader stacker 1
POS2 32 position, shared stacker 2/8
POS4 32 position, punch stacker 4
Error handling is as follows:
device error processed as
reader end of file if SSA set, set LAST indicator
on next Read, report error and stop
reader,punch not attached report error and stop
OS I/O error print error message
if IOCHK set, report error and stop
otherwise, set ERR indicator
stacker not attached ignored
OS I/O error print error message
if IOCHK set, report error and stop
2.3 1403 Line Printer (LPT)
The IBM 1403 line printer (LPT) writes its data, converted to ASCII, to
a disk file. The line printer implements both 48- and 64-character print
chains:
SET LPT 64 64-character print chain
SET LPT 48 48-character print chain
The line printer also implements both the business (1403 print chain
A) and Fortran (1403 H chain) character sets:
SET LPT BUSINESS business print character set
SET LPT FORTRAN Fortran character set
The default is the 64 character print chain with the business set.
In addition, the line printer can be programmed with a carriage control
tape. The LOAD command loads a new carriage control tape:
LOAD <file> load carriage control tape file
The format of a carriage control tape consists of multiple lines. Each
line contains an optional repeat count, enclosed in parentheses, optionally
followed by a series of column numbers separated by commas. Column numbers
must be between 1 and 12; a column number of zero denotes top of form. The
following are all legal carriage control specifications:
<blank line> no punch
(5) 5 lines with no punches
1,5,7,8 columns 1, 5, 7, 8 punched
(10)2 10 lines with column 2 punched
1,0 column 1 punched; top of form
The default form is 66 lines long, with column 1 and the top of form mark
on line 1, and the rest blank.
The line printer registers are:
name size comments
LINES 8 number of newlines after next print
LFLAG 1 carriage control flag (1 = skip, 0 = space)
CCTP 8 carriage control tape pointer
CCTL 8 carriage control tape length (read only)
ERR 1 error indicator
POS 32 position
CCT[0:131] 32 carriage control tape array
Error handling is as follows:
error processed as
not attached report error and stop
OS I/O error print error message
if IOCHK set, report error and stop
otherwise, set ERR indicator
2.4 1407 Inquiry Terminal (INQ)
The IBM 1407 inquiry terminal (INQ) is a half-duplex console. It polls
the console keyboard periodically for inquiry requests.
The inquiry terminal supports both the business (1403 print chain A)
and Fortran (1403 H chain) character sets for output:
SET INQ BUSINESS business character set
SET INQ FORTRAN Fortran character set
The business character set is the default.
The inquiry terminal registers are:
name size comments
INQC 7 inquiry request character (initially ESC)
INR 1 inquiry request indicator
INC 1 inquiry cleared indicator
TIME 24 polling interval
When the 1401 CPU requests input from the keyboard, the message [Enter]
is printed out, followed by a new line. The CPU hangs waiting for input
until either the return/enter key is pressed, or the inquiry request
character is typed in. The latter cancels the type-in and sets INC.
The inquiry terminal has no errors.
2.5 1311 Disk Pack (DP)
The disk pack controller supports 5 drives, numbered 0 through 4. Disk
pack options include the ability to enable address writing (formatting).
SET DPn ADDROFF set unit n address enable off
SET DPn ADDRON set unit n address enable on
Units can also be set ENABLED or DISABLED.
Unlike most simulated disks, the 1311 includes explicit representation
for sector addresses. This is to support non-standard formats, such as
the inclusion of the drive number in the sector address. As a result,
1311 sectors are 106 characters long: 6 address characters and 100
data characters. If the 1311 has not been formatted, the addresses
are blanks and are synthesized, if needed, based on the sector number.
The 1311 also supports two modes of operation: move mode and load mode.
In move mode, word marks are ignored on writes and left untouched on reads,
and sectors hold 100 characters. In load mode, word marks are included
on writes and stored on reads, and sectors hold 90 characters. No attempt
is made to deal with sectors written in load mode and read in move mode,
or vice versa; on a real 1401, this causes a fatal parity error.
The disk pack controller implements these registers:
name size comments
ACC 1 access error indicator
PWC 1 parity or write check error indicator
WLR 1 wrong length record error indicator
UNA 1 unequal address compare error indicator
DSK 1 any disk error indicator
BSY 1 disk access busy indicator
LASTF 3 most recent function
TIME 24 seek time
The 1311 has a primative overlapped seek capability. If TIME is set
non-zero, the 1311 will report itself busy for the specified amount
of time following a seek. This allows programs to utilize the seek
time for processing.
Error handling is as follows:
error processed as
not attached set DSK indicator
if IOCHK set, report error and stop
1311 data files are buffered in memory; therefore, end of file and OS
I/O errors cannot occur.
2.6 729 Magnetic Tape (MT)
The magnetic tape controller supports six drives, numbered 1 through 6.
Magnetic tape options include the ability to make units write enabled or
or write locked.
SET MTn LOCKED set unit n write locked
SET MTn WRITEENABLED set unit n write enabled
Units can also be set ENABLED or DISABLED. The magnetic tape simulator
supports the BOOT command. BOOT MT reads the first record off tape,
starting at location 1, and then branches to it.
The magnetic tape controller implements these registers:
name size comments
END 1 end of file indicator
ERR 1 error indicator
PAR 1 parity error indicator
POS1..6 32 position, drives 1..6
Error handling is as follows:
error processed as
not attached report error and stop
end of file set error indicator
OS I/O error print error message
set error indicator
if IOCHK set, report error and stop
2.7 Symbolic Display and Input
The IBM 1401 simulator implements symbolic display and input. Display is
controlled by command line switches:
-c display as single character
(BCD for CPU and MT, ASCII for others)
-s display as wordmark terminated BCD string
(CPU only)
-m display instruction mnemonics
(CPU only)
-d display 50 characters per line, with word
marks denoted by "1" on the line below
In a CPU character display, word marks are denoted by `.
Input parsing is controlled by the first character typed in or by command
line switches:
' or " or -c or -s characters (BCD for CPU and MT, ASCII
for others)
alphabetic instruction mnemonic
numeric octal number
Instruction input is free format, with spaces separating fields. There
are six instruction formats: 1, 2, 4, 5, 7, and 8 characters:
1 character opcode
2 character opcode 'modifier
4 character opcode address
5 character opcode address 'modifier
7 character opcode address address
8 character opcode address address 'modifier
Addresses are always decimal, except for special I/O addresses in the A
field, which may be specified as %xy, where x denotes the device and y
the unit number.
For the CPU, string input may encompass multiple characters. A word mark
is denoted by ~ and must precede the character to be marked. All other
devices can only accept single character input, without word marks.
2.7 Character Sets
The IBM 1401 uses a 6b character code called BCD (binary coded decimal).
Some of the characters have no equivalent in ASCII and require different
representations:
BCD ASCII IBM 1401 print
code representation character chains
00 space
01 1
02 2
03 3
04 4
05 5
06 6
07 7
10 8
11 9
12 0
13 # or = = in H chain
14 @ or ' ' in H chain
15 : blank in A, H chains
16 > blank in A, H chains
17 { tape mark blank in A, H chains
20 ^ alternate blank blank in A, H chains
21 /
22 S
23 T
24 U
25 V
26 W
27 X
30 Y
31 Z
32 | record mark
33 ,
34 % or ( ( in H chain
35 ~ word mark blank in A, H chains
36 \ blank in A, H chains
37 " blank in A, H chains
40 -
41 J
42 K
43 L
44 M
45 N
46 O
47 P
50 Q
51 R
52 !
53 $
54 *
55 ] blank in A, H chains
56 ; blank in A, H chains
57 _ delta blank in A, H chains
60 &
61 A
62 B
63 C
64 D
65 E
66 F
67 G
70 H
71 I
72 ?
73 .
74 ) lozenge
75 [ blank in A, H chains
76 < blank in A, H chains
77 } group mark blank in A, H chains
2.8 Old Conversions
Starting with V3.5-1, the 1401 simulator was changed to use the same character
set as the 7094 (and other 7094 simulators). This involved the following changes
code V3.5-0 or earlier V3.5-1 or later
13 # # or = on input
14 @ @ or ' on input
17 ( {
32 ' |
34 % % or ( on input
35 = ~
37 + "
60 & & or + on input
77 " }
In addition, the word mark indicator was changed from ~ to `.
The 1401 simulator can be set to operate with either set of conventions:
SET CPU OLDCONVERSIONS
SET CPU NEWCONVERSIONS
The default is NEWCONVERSIONS.

View file

@ -1,6 +1,6 @@
/* i1401_mt.c: IBM 1401 magnetic tape simulator /* i1401_mt.c: IBM 1401 magnetic tape simulator
Copyright (c) 1993-2005, Robert M. Supnik Copyright (c) 1993-2006, Robert M. Supnik
Permission is hereby granted, free of charge, to any person obtaining a Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"), copy of this software and associated documentation files (the "Software"),
@ -25,6 +25,7 @@
mt 7-track magtape mt 7-track magtape
16-Feb-06 RMS Added tape capacity checking
15-Sep-05 RMS Yet another fix to load read group mark plus word mark 15-Sep-05 RMS Yet another fix to load read group mark plus word mark
Added debug printouts (from Van Snyder) Added debug printouts (from Van Snyder)
26-Aug-05 RMS Revised to use API for write lock check 26-Aug-05 RMS Revised to use API for write lock check
@ -128,6 +129,8 @@ MTAB mt_mod[] = {
{ MTUF_WLK, MTUF_WLK, "write locked", "LOCKED", NULL }, { MTUF_WLK, MTUF_WLK, "write locked", "LOCKED", NULL },
{ MTAB_XTD|MTAB_VUN, 0, "FORMAT", "FORMAT", { MTAB_XTD|MTAB_VUN, 0, "FORMAT", "FORMAT",
&sim_tape_set_fmt, &sim_tape_show_fmt, NULL }, &sim_tape_set_fmt, &sim_tape_show_fmt, NULL },
{ MTAB_XTD|MTAB_VUN, 0, "CAPACITY", "CAPACITY",
&sim_tape_set_capac, &sim_tape_show_capac, NULL },
{ 0 } { 0 }
}; };
@ -224,6 +227,7 @@ t_stat mt_io (int32 unit, int32 flag, int32 mod)
int32 t, wm_seen; int32 t, wm_seen;
t_mtrlnt i, tbc; t_mtrlnt i, tbc;
t_stat st; t_stat st;
t_bool passed_eot;
UNIT *uptr; UNIT *uptr;
if ((uptr = get_unit (unit)) == NULL) return STOP_INVMTU; /* valid unit? */ if ((uptr = get_unit (unit)) == NULL) return STOP_INVMTU; /* valid unit? */
@ -300,7 +304,10 @@ switch (mod) {
} }
} }
if (DEBUG_PRS (mt_dev)) fprintf (sim_deb, " to %d\n", BS - 1); if (DEBUG_PRS (mt_dev)) fprintf (sim_deb, " to %d\n", BS - 1);
passed_eot = sim_tape_eot (uptr); /* passed EOT? */
st = sim_tape_wrrecf (uptr, dbuf, tbc); /* write record */ st = sim_tape_wrrecf (uptr, dbuf, tbc); /* write record */
if (!passed_eot && sim_tape_eot (uptr)) /* just passed EOT? */
ind[IN_END] = 1;
if (ADDR_ERR (BS)) { /* check final BS */ if (ADDR_ERR (BS)) { /* check final BS */
BS = BA | (BS % MAXMEMSIZE); BS = BA | (BS % MAXMEMSIZE);
return STOP_WRAP; return STOP_WRAP;

View file

@ -1,533 +0,0 @@
To: Users
From: Bob Supnik
Subj: IBM 1620 Simulator Usage
Date: 15-Sep-2005
COPYRIGHT NOTICE
The following copyright notice applies to both the SIMH source and binary:
Original code published in 1993-2005, written by Robert M Supnik
Copyright (c) 1993-2005, Robert M Supnik
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Except as contained in this notice, the name of Robert M Supnik shall not be
used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from Robert M Supnik.
This memorandum documents the IBM 1620 simulator. This simulator is based on
Geoff Kuenning's 1620 simulator, which is used by permission.
1. Simulator Files
sim/ scp.h
sim_console.h
sim_defs.h
sim_fio.h
sim_rev.h
sim_sock.h
sim_timer.h
sim_tmxr.h
scp.c
sim_console.c
sim_fio.c
sim_sock.c
sim_timer.c
sim_tmxr.c
sim/i1620/ i1620_defs.h
i1620_cpu.c
i1620_fp.c
i1620_tty.c
i1620_pt.c
i1620_cd.c
i1620_lp.c
i1620_dp.c
i1620_sys.c
2. IBM 1620 Features
The IBM 1620 simulator is configured as follows:
device simulates
name(s)
CPU IBM 1620 Model 1 or Model 2 CPU with 20K to 60K of memory
Model 1 options: indirect addressing, automatic divide,
edit instructions, floating point
Model 2 options: indexing, binary capability, floating point
TTY IBM console terminal
PTR IBM 1621 paper tape reader
PTP IBM 1624 paper tape punch
CDR,CDP IBM 1622 card reader/punch
LPT IBM 1443 line printer
DP IBM 1311 disk pack with four drives
The IBM 1620 simulator implements many unique stop conditions. On almost
any kind of error the simulator stops:
unimplemented opcode
reference to non-existent device
invalid digit
invalid alphameric character
invalid P address digit
invalid Q address digit
indirect address limit exceeded
invalid odd address
invalid even address
invalid function
invalid indicator
invalid return address register
skip to unpunched carriage control tape channel
card reader hopper empty
overflow with arithmetic stop switch set
I/O error with I/O stop switch set
invalid disk drive
invalid disk sector address
invalid disk sector count
invalid disk buffer address
disk address compare error
disk cylinder overflow error
disk write check error
field exceeds memory
record exceeds memory
floating point mantissa exceeds maximum length
floating point mantissas not the same length
floating point exponent check with arithmetic stop switch set
floating point exponent missing high flag
The LOAD command is used to load a line printer carriage-control tape.
The DUMP command is not implemented.
2.1 CPU
The CPU options include the CPU model (Model 1 or Model 2), a number of
special features, and the size of main memory.
SET CPU IA enable indirect addressing
SET CPU NOIA disable indirect addressing
SET CPU EDT enable extra editing instructions
SET CPU NOEDT disable extra editing instructions
SET CPU DIV enable divide instructions
SET CPU NODIV disable divide instructions
SET CPU IDX enable indexing
SET CPU NOIDX disable indexing
SET CPU BIN enable binary instructions
SET CPU NOBIN disable binary instructions
SET CPU FP enable floating point instructions
SET CPU NOFP disable floating point instructions
SET CPU MOD1 set Model 1
SET CPU MOD2 set Model 2
SET CPU 20K set memory size = 20K
SET CPU 40K set memory size = 40K
SET CPU 60K set memory size = 60K
Model 1 options include IA, EDT, DIV, and FP; the first three are on by
default. Model 2 options include IDX, BIN, and FP; IA, EDT, and DIV are
standard on the Model 2.
If memory size is being reduced, and the memory being truncated contains
non-zero data, the simulator asks for confirmation. Data in the truncated
portion of memory is lost. Initially, the CPU is a Model 1, memory size is
20K, and indirect addressing, editing instructions, and divide are enabled.
Memory is implemented as 5 bit BCD digits, as follows:
4 3 2 1 0
flag 8 4 2 1
<-------- digit -------->
In BCD, the decimal digits 0-9 are (hex) values 0x0, 0x1, 0x2, 0x3, 0x4,
0x5, 0x6, 0x7, 0x8, 0x9, respectively. 0xA is record mark, 0xC non-
punching blank, and 0xF group mark, respectively.
CPU registers include the visible state of the processor. The 1620 has no
interrupt system.
name size comments
IR1 16 instruction storage address register (PC)
IR2 16 return register
PR1 16 processor register 1
PAR 16 P address register (OR2)
QAR 16 Q address register (OR1)
SS1 1 sense switch 1
SS2 1 sense switch 2
SS3 1 sense switch 3
SS4 1 sense switch 4
HP 1 high/positive indicator
EZ 1 equal/zero indicator
ARCHK 1 arithmetic check (overflow) indicator
EXPCHK 1 exponent check indicator
RDCHK 1 read check indicator
WRCHK 1 write check indicator
ARSTOP 1 arithmetic check stop switch
IOSTOP 1 I/O check stop switch
IND[0:99] 1 indicator array
IAE 1 indirect address enable (Model 2 only)
IDXE 1 indexing enable (Model 2 only)
IDXB 1 indexing band select (Model 2 only)
IR1Q[0:63] 16 IR1 prior to last branch;
most recent IR1 change first
WRU 8 interrupt character
The CPU can maintain a history of the most recently executed instructions.
This is controlled by the SET CPU HISTORY and SHOW CPU HISTORY commands:
SET CPU HISTORY clear history buffer
SET CPU HISTORY=0 disable history
SET CPU HISTORY=n enable history, length = n
SHOW CPU HISTORY print CPU history
SHOW CPU HISTORY=n print first n entries of CPU history
The maximum length for the history is 65536 entries.
2.2 Console Typewriter (TTY)
The console typewriter (TTY) is a half-duplex console. The typewriter
registers are:
name size comments
COL 7 current column
TIME 24 polling interval
When the 1620 CPU requests input from the keyboard, a greater than sign
(>) is printed. The CPU hangs waiting for input until the return/enter
key is pressed. The typewriter has no errors.
2.3 1621 Paper Tape Reader (PTR)
The paper tape reader (PTR) reads data from a disk file. The POS register
specifies the number of the next data item to be read. Thus, by changing
POS, the user can backspace or advance the reader.
The paper tape reader supports the BOOT command. BOOT PTR starts the
standard paper tape boot sequence at location 0.
The paper tape reader implements these registers:
name size comments
POS 32 position in the input file
Error handling is as follows:
error IOCHK processed as
not attached x set RDCHK indicator, report error, stop
end of file x set RDCHK indicator, report error, stop
OS I/O error x set RDCHK indicator, report error, stop
parity error 1 set RDCHK indicator, report error, stop
0 set RDCHK indicator
2.4 1624 Paper Tape Punch (PTP)
The paper tape punch (PTP) writes data to a disk file. The POS register
specifies the number of the next data item to be written. Thus, by
changing POS, the user can backspace or advance the punch.
The paper tape punch implements these registers:
name size comments
POS 32 position in the output file
Error handling is as follows:
error IOCHK processed as
not attached x set WRCHK indicator, report error, stop
OS I/O error x set WRCHK indicator, report error, stop
invalid char 1 set WRCHK indicator, report error, stop
0 set WRCHK indicator
2.5 1622 Card Reader/Punch (CDR, CDP)
The IBM 1402 card/reader punch is simulated as two independent devices:
the card reader (CDR) and the card punch (CDP).
The card reader supports the BOOT command. BOOT CDR starts the standard
card boot sequence at location 0.
The card reader reads data from a disk file, while the punch writes data
to a disk file. Cards are simulated as ASCII text lines with terminating
newlines. For each unit, the POS register specifies the number of the
next data item to be read or written. Thus, by changing POS, the user
can backspace or advance these devices.
The card reader registers are:
name size comments
LAST 1 last card indicator
POS 32 position
The card punch registes are:
name size comments
POS 32 position
Card reader error handling is as follows:
error IOCHK processed as
end of file x set RDCHK indicator, report error, stop
not attached x set RDCHK indicator, report error, stop
OS I/O error x set RDCHK indicator, report error, stop
invalid char 1 set RDCHK indicator, report error, stop
0 set RDCHK indicator
Card punch error handling is as follows:
error IOCHK processed as
not attached x set WRCHK indicator, report error, stop
OS I/O error x set WRCHK indicator, report error, stop
invalid char 1 set WRCHK indicator, report error, stop
0 set WRCHK indicator
2.6 1443 Line Printer (LPT)
The IBM 1443 line printer (LPT) writes its data, converted to ASCII, to
a disk file. The line printer can be programmed with a carriage control
tape. The LOAD command loads a new carriage control tape:
LOAD <file> load carriage control tape file
The format of a carriage control tape consists of multiple lines. Each
line contains an optional repeat count, enclosed in parentheses, optionally
followed by a series of column numbers separated by commas. Column numbers
must be between 1 and 12; a column number of zero denotes top of form. The
following are all legal carriage control specifications:
<blank line> no punch
(5) 5 lines with no punches
1,5,7,8 columns 1, 5, 7, 8 punched
(10)2 10 lines with column 2 punched
1,0 column 1 punched; top of form
The default form is 66 lines long, with column 1 and the top of form mark
on line 1, and the rest blank.
The line printer registers are:
name size comments
LBUF[0:119] 7 line buffer
BPTR 7 buffer pointer
PCTL 8 saved print control directive
PRCHK 1 print check indicator
PRCH9 1 channel 9 indicator
PRCH12 1 channel 12 indicator
POS 32 position
CCT[0:131] 32 carriage control tape array
CCTP 8 carriage control tape pointer
CCTL 8 carriage control tape length (read only)
Error handling is as follows:
error IOCHK processed as
not attached x set PRCHK, WRCHK indicators, report error, stop
OS I/O error x set PRCHK, WRCHK indicators, report error, stop
invalid char 1 set PRCHK, WRCHK indicator, report error, stop
0 set PRCHK, WRCHK indicator
2.7 1311 Disk Pack (DP)
The disk pack controller supports 4 drives, numbered 0 through 3. Disk
pack options include the ability to enable address writing (formatting).
SET DPn ADDROFF set unit n address enable off
SET DPn ADDRON set unit n address enable on
Units can also be set ENABLED or DISABLED.
Unlike most simulated disks, the 1311 includes explicit representation
for sector addresses. This is to support non-standard formats, such as
the inclusion of the drive number in the sector address. As a result,
1311 sectors are 105 digits long: 5 address digits and 100 data digits.
If the 1311 has not been formatted, the addresses are zeroes and are
synthesized, if needed, based on the sector number.
The disk pack controller implements these registers:
name size comments
ADCHK 1 address check (compare error) indicator
WLRC 1 wrong length record check indicator
CYLO 1 cylinder overflow check indicator
ERR 1 disk error indicator
DPSTOP 1 disk check stop
Error handling is as follows:
error DPCHK processed as
not attached x set ERR indicator, report error, stop
1311 data files are buffered in memory; therefore, end of file and OS
I/O errors cannot occur.
2.8 Symbolic Display and Input
The IBM 1620 simulator implements symbolic display and input. Display is
controlled by command line switches:
-c display as single character (alphameric
for CPU and DP, ASCII for others)
-s display as flag terminated alphameric string
(CPU and DP only)
-m display instruction mnemonics
(CPU and DP only)
-d display 50 characters per line, with word
marks denoted by "_" on the line above
Input parsing is controlled by the first character typed in or by command
line switches:
' or -c character (alphameric for CPU and DP, ASCII
for others)
" or -s alphameric string (CPU and DP only)
alphabetic instruction mnemonic (CPU and DP only)
numeric octal number
Instruction input is free format and consists of an opcode and up to
three operands:
op {+/-}ppppp{(idx)},{+-}qqqqq{(idx)},flags
The p address and, if present, the q address, are always decimal. A
plus sign is ignored; a minus sign denotes indirect addressing (or a
negative immediate operand). If indexing is enabled, addresses may
be indexed; index registers are decimal numbers between 1 and 7. The
flags field is used to set extra flags on the instruction. It consists
of digit numbers in ascending order, with no separators. For example,
AM -12345(5),67890,110
translates into
_ _ ___ _
111234567890
The flag over digits 3 and 5 specify the P index register; the flag
over digit 6 specifies the P indirect address; the flag over digit 7
marks the end of the immediate Q operand; and the flags over digits
1 and 10 are specified by the third field.
2.9 Character Sets
The IBM 1620 uses single digits to represent numbers, and pairs of
digits to represent characters (alphameric coding). Only a small
number of the 256 possible alphameric codings have legitimate values.
Further, the translation between alphameric and devices varied from
device to device. The simulator implements a code called 1620 ASCII,
which allows all 64 possible card codes to be represented by upper
case ASCII characters. In addition, lower case alphabetic characters
are accepted on input as equivalent to upper case.
Card code PT code RA RN LPT WA ASCII representation
<blank> C 0 0 blank blank
1 1 71 1 1 1
2 2 72 2 2 2
3 C21 73 3 3 3
4 4 74 4 4 4
5 C41 75 5 5 5
6 C42 76 6 6 6
7 421 77 7 7 7
8 8 78 8 8 8
9 C81 79 9 9 9
2 + 8 C82 ? 0A A na ^
3 + 8 821 33 B = = (or #)
4 + 8 C84 34 C @ @ (or ')
5 + 8 841 70 0 0 :
6 + 8 842 ? 0E E na >
7 + 8 C8421 ? 0F F na {
12 XOC 10 0 + + (or &)
12 + 1 XO1 41 1 A A
12 + 2 XO2 42 2 B B
12 + 3 XOC21 43 3 C C
12 + 4 XO4 44 4 D D
12 + 5 XOC41 45 5 E E
12 + 6 XOC42 46 6 F F
12 + 7 XO421 47 7 G G
12 + 8 XO8 48 8 H H
12 + 9 XOC81 49 9 I I
12 + 2 + 8 XOC82 ? 5A ? F+A na ?
12 + 3 + 8 XO821 3 ? F+B . .
12 + 4 + 8 XOC84 4 C ) )
12 + 5 + 8 XO841 40 0 na [
12 + 6 + 8 XO842 ? 5E ? F+E na <
12 + 7 + 8 XOC8421 5F F+F na }
11 X 20 F+0 - -
11 + 1 XC1 51 F+1 J J
11 + 2 XC2 52 F+2 K K
11 + 3 X21 53 F+3 L L
11 + 4 XC4 54 F+4 M M
11 + 5 X41 55 F+5 N N
11 + 6 X42 56 F+6 O O
11 + 7 XC421 57 F+7 P P
11 + 8 XC8 58 F+8 Q Q
11 + 9 X81 59 F+9 R R
11 + 2 + 8 X82 5A F+A na !
11 + 3 + 8 XC821 13 F+B $ $
11 + 4 + 8 X84 14 F+C * *
11 + 5 + 8 XC841 50 F+0 - ]
11 + 6 + 8 XC842 ? 5E ? F+E na ;
11 + 7 + 8 X8421 5F F+F na _
0 O 70 0 0 0
0 + 1 OC1 21 1 / /
0 + 2 OC2 62 2 S S
0 + 3 O21 63 3 T T
0 + 4 OC4 64 4 U U
0 + 5 O41 65 5 V V
0 + 6 O42 66 6 W W
0 + 7 OC421 67 7 X X
0 + 8 OC8 68 8 Y Y
0 + 9 O81 69 9 Z Z
0 + 2 + 8 O82 0A A na |
0 + 3 + 8 OC821 23 B , ,
0 + 4 + 8 O84 24 C ( ( (or %)
0 + 5 + 8 OC841 60 0 na ~
0 + 6 + 8 OC842 0E E na \
0 + 7 + 8 O8421 0F F na "
2 ?
12 !
22 |
32 0
35 :
36 blank
11 + 0 50 - `

72
I7094/i7094_bugs.txt Normal file
View file

@ -0,0 +1,72 @@
Bugs found
1. CPU: MPY tested sign of AC instead of sign of MQ.
2. CPU: VLM, VDP, VDH need alternate opcode decode points for large counts.
3. CPU: STL not in decode table.
4. CPU: Partial stores lacked initial read in decode table.
5. CPU: PXD, PCD needed (t_uint64) cast.
6. CPU: SXD, SCD needed (t_uint64) cast.
7. CPU: SBM at wrong case offset.
8. CPU: All transfers used IR<21:35> instead of calculated effective address.
9. CPU: HPR, TRA need alternate negative opcodes.
10. CPU: STT missing final write to memory.
11. IO: Channel output process model incorrect, extensive revision required.
12. IO: Channel connect test should not test channel state, only connection.
13. IO: Channel opcode with nostore doesn't increment channel address.
14. CDR: Card reader missing activate at end of state 2.
15. SYS: Zero operand instructions printed with trailing space.
16. CPU: Convert class count bit field start definition incorrect.
17. CPU: CAQ cut and paste error from CVR.
18. CPU: Shift count is 8b wide, not 9b.
19. SYS: Mnemonic is LDQ not LMQ.
20. SYS: RQL opcode incorrect in symbolic decode table.
21. CPU: Multi-tag mode stores OR'd value of tags on any index read except
normal effective address.
22. CPU: Floating point trap does not write location 0 if trap suppressed.
23. SYS: TRA instructions should have symbolic class MXN not MXR.
24. CPU: Floating add instructions test for zero result only if normalization enabled.
25. CPU: Floating add with unlike signs and equal magnitudes, result sign is sign
of SR rather than sign of AC.
26. CPU: Floating multiply does not test spill prior to normalization step.
27. CPU: Channel activity proceeds under HALT.
28. MT: Any read error should stop the channel and the tape controller.
29. MT: EOR write flag cleared before testing.
39. IO: EOR write flag set after data sent to device.
40. IO: EOR write flag incorrect set on IOCP, IOCT, IOSP, IOST.
41. MT: End of file errors not masked on backspace operations.
42. CPU: LCHx, RCHx miscoded in decode table.
43. IO: Only 7607 error completions (IOxT without new command) set trap.
44. CPU: 7067 channel trap flags misdefined with extraneous decrement shift.
45. CPU: pcq array misdeclared as uint32 instead of uint16.
46. IO: SDC and SCD tested chan_flags instead of chan_dev.flags.
47. SYS: 7907 opcodes defined incorrectly.
48. SYS: TCH not decoding bit<19>.
49. IO: CTL not clearing EOR after device end.
50. DSK: Format code not incrementing track in writing all tracks in cylinder.
51. DSK: THA mode overwrites record structure of first record.
52. DSK: Write doesn't set channel request for initial word.
53. DSK: Saved record number was command digits 3..8 instead of 5..10.
54. CLK: Compute 60th's from location 5, so Chrono clock is in sync with interval clock.
55. CPU: Enable Chronolog clock if CTSS.
56. CPU: Read/write protection error not setting protection trap.
57. CPU: SCHx not setting protection trap in user mode.
58: CPU: Protection trap overwriting wrong location.
59. CPU: Stop message reporting physical, not virtual, PC.
60. IO: Test for "request another cycle" in channel processor was inverted.
61. IO: Valid bit handling incorrect across multiple transfers.
62. IO: BSR doesn't set EOF indicator.
63. IO: 7607 channel modeled incorrectly, could stall.
64. IO: All 7607 "effective NOP" conditions must be tested when a new command is
decoded (wc == 0 for IOCx and IOSx, EOR set for IOSx and IORx).

495
I7094/i7094_cd.c Normal file
View file

@ -0,0 +1,495 @@
/* i7094_cd.c: IBM 711/721 card reader/punch
Copyright (c) 2003-2006, 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.
cdr 711 card reader
cdp 721 card punch
Cards are represented as ASCII text streams terminated by newlines.
This allows cards to be created and edited as normal files. Two
formats are supported:
column binary each character represents 6b of a 12b column
text each character represents all 12b of a column
Internally, the 7094 works only with column binary and is limited
to 72 columns of data. Each row of the card is represented by 72b
of data (two 36b words). A complete card image consists of 12 rows
(24 36b words).
*/
#include "i7094_defs.h"
#define CD_BINLNT 24 /* bin buf length */
#define CD_CHRLNT 80 /* char buf length */
#define CDS_INIT 0 /* card in motion */
#define CDS_DATA 1 /* data transfer */
#define CDS_END 2 /* card complete */
#define UNIT_V_CBN (UNIT_V_UF + 0) /* column binary file */
#define UNIT_V_PCA (UNIT_V_UF + 1) /* A vs H punch flag */
#define UNIT_CBN (1 << UNIT_V_CBN)
#define UNIT_PCA (1 << UNIT_V_PCA)
uint32 cdr_sta = 0; /* state */
uint32 cdr_bptr = 0; /* buffer ptr */
uint32 cdr_tstart = 27500; /* timing */
uint32 cdr_tstop = 27500;
uint32 cdr_tleft = 150;
uint32 cdr_tright = 4000;
t_uint64 cdr_bbuf[CD_BINLNT]; /* col binary buf */
uint32 cdp_sta = 0; /* state */
uint32 cdp_bptr = 0; /* buffer ptr */
uint32 cdp_tstart = 35000; /* timing */
uint32 cdp_tstop = 35000;
uint32 cdp_tleft = 150;
uint32 cdp_tright = 15500;
t_uint64 cdp_chob = 0;
uint32 cdp_chob_v = 0;
t_uint64 cdp_bbuf[CD_BINLNT]; /* col binary buf */
t_stat cdr_chsel (uint32 ch, uint32 sel, uint32 unit);
t_stat cdr_reset (DEVICE *dptr);
t_stat cdr_svc (UNIT *uptr);
t_stat cdr_boot (int32 unitno, DEVICE *dptr);
t_stat cdp_chsel (uint32 ch, uint32 sel, uint32 unit);
t_stat cdp_chwr (uint32 ch, t_uint64 val, uint32 flags);
t_stat cdp_reset (DEVICE *dptr);
t_stat cdp_svc (UNIT *uptr);
t_stat cdp_card_end (UNIT *uptr);
t_stat cd_attach (UNIT *uptr, char *cptr);
t_stat cd_set_mode (UNIT *uptr, int32 val, char *cptr, void *desc);
char colbin_to_bcd (uint32 cb);
extern uint32 sim_switches;
extern uint32 PC;
extern uint32 ind_ioc;
extern char bcd_to_ascii_a[64];
extern char bcd_to_ascii_h[64];
extern uint32 bcd_to_colbin[64];
extern char ascii_to_bcd[128];
extern t_uint64 bit_masks[36];
extern uint32 col_masks[12];
/* Card reader data structures
cdr_dev CDR descriptor
cdr_unit CDR unit descriptor
cdr_reg CDR register list
*/
DIB cdr_dib = { &cdr_chsel, NULL };
UNIT cdr_unit = {
UDATA (&cdr_svc, UNIT_SEQ+UNIT_ATTABLE+UNIT_ROABLE, 0)
};
REG cdr_reg[] = {
{ ORDATA (STATE, cdr_sta, 2) },
{ DRDATA (BPTR, cdr_bptr, 5), PV_LEFT },
{ BRDATA (BUF, cdr_bbuf, 8, 36, CD_BINLNT) },
{ DRDATA (POS, cdr_unit.pos, T_ADDR_W), PV_LEFT },
{ DRDATA (TSTART, cdr_tstart, 24), PV_LEFT + REG_NZ },
{ DRDATA (TSTOP, cdr_tstop, 24), PV_LEFT + REG_NZ },
{ DRDATA (TLEFT, cdr_tleft, 24), PV_LEFT + REG_NZ },
{ DRDATA (TRIGHT, cdr_tright, 24), PV_LEFT + REG_NZ },
{ NULL } };
MTAB cdr_mod[] = {
{ UNIT_CBN, UNIT_CBN, "column binary", "BINARY", &cd_set_mode },
{ UNIT_CBN, UNIT_CBN, "text", "TEXT", &cd_set_mode },
{ 0 }
};
DEVICE cdr_dev = {
"CDR", &cdr_unit, cdr_reg, cdr_mod,
1, 10, 31, 1, 8, 7,
NULL, NULL, &cdr_reset,
&cdr_boot, &cd_attach, NULL,
&cdr_dib, DEV_DISABLE
};
/* CDP data structures
cdp_dev CDP device descriptor
cdp_unit CDP unit descriptor
cdp_reg CDP register list
*/
DIB cdp_dib = { &cdp_chsel, &cdp_chwr };
UNIT cdp_unit = {
UDATA (&cdp_svc, UNIT_SEQ+UNIT_ATTABLE, 0)
};
REG cdp_reg[] = {
{ ORDATA (STATE, cdp_sta, 2) },
{ ORDATA (CHOB, cdp_chob, 36) },
{ FLDATA (CHOBV, cdp_chob_v, 0) },
{ DRDATA (BPTR, cdp_bptr, 5), PV_LEFT },
{ BRDATA (BUF, cdp_bbuf, 8, 36, CD_BINLNT) },
{ DRDATA (POS, cdp_unit.pos, T_ADDR_W), PV_LEFT },
{ DRDATA (TSTART, cdp_tstart, 24), PV_LEFT + REG_NZ },
{ DRDATA (TSTOP, cdp_tstop, 24), PV_LEFT + REG_NZ },
{ DRDATA (TLEFT, cdp_tleft, 24), PV_LEFT + REG_NZ },
{ DRDATA (TRIGHT, cdp_tright, 24), PV_LEFT + REG_NZ },
{ NULL }
};
MTAB cdp_mod[] = {
{ UNIT_CBN, UNIT_CBN, "column binary", "BINARY", &cd_set_mode },
{ UNIT_CBN, UNIT_CBN, "text", "TEXT", &cd_set_mode },
{ UNIT_PCA, UNIT_PCA, "business set", "BUSINESS", NULL },
{ UNIT_PCA, 0, "Fortran set", "FORTRAN", NULL },
{ 0 }
};
DEVICE cdp_dev = {
"CDP", &cdp_unit, cdp_reg, cdp_mod,
1, 10, 31, 1, 8, 7,
NULL, NULL, &cdp_reset,
NULL, &cd_attach, NULL,
&cdp_dib, DEV_DISABLE
};
/* Card reader select */
t_stat cdr_chsel (uint32 ch, uint32 sel, uint32 unit)
{
if (sel & CHSL_NDS) return ch6_end_nds (ch); /* nds? nop */
switch (sel) { /* case on data sel */
case CHSL_RDS: /* read */
if ((cdr_unit.flags & UNIT_ATT) == 0) /* not attached? */
return SCPE_UNATT;
if (sim_is_active (&cdr_unit)) /* busy? */
return ERR_STALL;
cdr_sta = CDS_INIT; /* initial state */
sim_activate (&cdr_unit, cdp_tstart); /* start reader */
break;
default: /* other */
return STOP_ILLIOP; /* not allowed */
}
return SCPE_OK;
}
/* Unit timeout */
t_stat cdr_svc (UNIT *uptr)
{
uint32 i, col, row, bufw, colbin;
char cdr_cbuf[2 * CD_CHRLNT + 1];
t_uint64 dat = 0;
if ((uptr->flags & UNIT_ATT) == 0) return SCPE_UNATT; /* not attached? */
switch (cdr_sta) { /* case on state */
case CDS_INIT: /* initial state */
for (i = 0; i < CD_BINLNT; i++) /* clear bin buf */
cdr_bbuf[i] = 0;
for (i = 0; i < ((2 * CD_CHRLNT) + 1); i++) /* clear char buf */
cdr_cbuf[i] = ' ';
cdr_sta = CDS_DATA; /* data state */
cdr_bptr = 0; /* init buf ptr */
fgets (cdr_cbuf, (uptr->flags & UNIT_CBN)? (2 * CD_CHRLNT): CD_CHRLNT,
uptr->fileref); /* read card */
if (feof (uptr->fileref)) /* eof? */
return ch6_err_disc (CH_A, U_CDR, CHF_EOF); /* set EOF, disc */
if (ferror (uptr->fileref)) { /* error? */
perror ("CDR I/O error");
clearerr (uptr->fileref);
return SCPE_IOERR; /* stop */
}
uptr->pos = ftell (uptr->fileref); /* update position */
for (i = 0; i < (2 * CD_CHRLNT); i++) /* convert to BCD */
cdr_cbuf[i] = ascii_to_bcd[cdr_cbuf[i] & 0177] & 077;
for (col = 0; col < 72; col++) { /* process 72 columns */
if (uptr->flags & UNIT_CBN) /* column binary? */
colbin = (((uint32) cdr_cbuf[2 * col]) << 6) |
((uint32) cdr_cbuf[(2 * col) + 1]); /* 2 chars -> col bin */
else colbin = bcd_to_colbin[cdr_cbuf[col]]; /* cvt to col binary */
dat = bit_masks[35 - (col % 36)]; /* mask for column */
for (row = 0; row < 12; row++) { /* rows 9..0, 11, 12 */
bufw = (row * 2) + (col / 36); /* index to buffer */
if (colbin & col_masks[row]) /* row bit set? */
cdr_bbuf[bufw] |= dat;
}
}
case CDS_DATA: /* data state */
dat = cdr_bbuf[cdr_bptr++]; /* get next word */
if (cdr_bptr >= CD_BINLNT) { /* last word? */
cdr_sta = CDS_END; /* end state */
ch6_req_rd (CH_A, U_CDR, dat, CH6DF_EOR); /* req chan, dat, EOR */
sim_activate (uptr, cdr_tstop);
}
else {
ch6_req_rd (CH_A, U_CDR, dat, 0); /* req chan, dat */
sim_activate (uptr, (cdr_bptr & 1)? cdr_tleft: cdr_tright);
}
break;
case CDS_END: /* end state */
if (ch6_qconn (CH_A, U_CDR)) { /* if cdr still conn */
cdr_sta = CDS_INIT; /* return to init */
sim_activate (uptr, 1); /* next card */
}
break;
}
return SCPE_OK;
}
/* Card reader reset */
t_stat cdr_reset (DEVICE *dptr)
{
uint32 i;
for (i = 0; i < CD_BINLNT; i++) cdr_bbuf[i] = 0; /* clear buffer */
cdr_sta = 0; /* clear state */
cdr_bptr = 0; /* clear buf ptr */
sim_cancel (&cdr_unit); /* stop reader */
return SCPE_OK;
}
/* Card reader bootstrap */
#define BOOT_START 01000
#define BOOT_SIZE (sizeof (boot_rom) / sizeof (t_uint64))
static const t_uint64 boot_rom[] = {
00762000001000 + U_CDR, /* RDSA CDR */
00544000000000 + BOOT_START + 4, /* LCHA *+3 */
00544000000000, /* LCHA 0 */
00021000000001, /* TTR 1 */
05000030000000, /* IOCT 3,,0 */
};
t_stat cdr_boot (int32 unitno, DEVICE *dptr)
{
uint32 i;
extern t_uint64 *M;
for (i = 0; i < BOOT_SIZE; i++)
WriteP (BOOT_START + i, boot_rom[i]);
PC = BOOT_START;
return SCPE_OK;
}
/* Reader/punch attach */
t_stat cd_attach (UNIT *uptr, char *cptr)
{
t_stat r = attach_unit (uptr, cptr);
if (r != SCPE_OK) return r; /* attach */
if (sim_switches & SWMASK ('T')) /* text? */
uptr->flags = uptr->flags & ~UNIT_CBN;
else if (sim_switches & SWMASK ('C')) /* column binary? */
uptr->flags = uptr->flags | UNIT_CBN;
else if (match_ext (cptr, "TXT")) /* .txt? */
uptr->flags = uptr->flags & ~UNIT_CBN;
else if (match_ext (cptr, "CBN")) /* .cbn? */
uptr->flags = uptr->flags | UNIT_CBN;
return SCPE_OK;
}
/* Reader/punch set mode - valid only if not attached */
t_stat cd_set_mode (UNIT *uptr, int32 val, char *cptr, void *desc)
{
return (uptr->flags & UNIT_ATT)? SCPE_NOFNC: SCPE_OK;
}
/* Card punch select */
t_stat cdp_chsel (uint32 ch, uint32 sel, uint32 unit)
{
if (sel & CHSL_NDS) return ch6_end_nds (ch); /* nds? nop */
switch (sel) { /* case on cmd */
case CHSL_WRS: /* write */
if ((cdp_unit.flags & UNIT_ATT) == 0) /* not attached? */
return SCPE_UNATT;
if (sim_is_active (&cdp_unit)) /* busy? */
return ERR_STALL;
cdp_sta = CDS_INIT; /* initial state */
sim_activate (&cdp_unit, cdp_tstart); /* start punch */
break;
default: /* other */
return STOP_ILLIOP; /* not allowed */
}
return SCPE_OK;
}
/* Channel write routine - write word to buffer, write card when full */
t_stat cdp_chwr (uint32 ch, t_uint64 val, uint32 eorfl)
{
cdp_chob = val & DMASK; /* store data */
cdp_chob_v = 1; /* buffer valid */
if (cdp_sta == CDS_DATA) {
cdp_bbuf[cdp_bptr++] = cdp_chob; /* store data */
if ((cdp_bptr >= CD_BINLNT) || eorfl) { /* end card or end rec? */
ch6_set_flags (CH_A, U_CDP, CHF_EOR); /* set eor */
return cdp_card_end (&cdp_unit); /* write card */
}
return SCPE_OK;
}
return SCPE_IERR;
}
/* Unit timeout */
t_stat cdp_svc (UNIT *uptr)
{
uint32 i;
switch (cdp_sta) { /* case on state */
case CDS_INIT: /* initial state */
for (i = 0; i < CD_BINLNT; i++) /* clear bin buffer */
cdp_bbuf[i] = 0;
cdp_sta = CDS_DATA; /* data state */
cdp_bptr = 0; /* init pointer */
ch6_req_wr (CH_A, U_CDP); /* request channel */
cdp_chob = 0; /* clr, inval buffer */
cdp_chob_v = 0;
sim_activate (uptr, cdp_tleft); /* go again */
break;
case CDS_DATA: /* data state */
if (!ch6_qconn (CH_A, U_CDP)) /* chan disconnect? */
return cdp_card_end (uptr); /* write card */
if (cdp_chob_v) cdp_chob_v = 0; /* valid? clear */
else ind_ioc = 1; /* no, io check */
ch6_req_wr (CH_A, U_CDP); /* req channel */
sim_activate (uptr, (cdp_bptr & 1)? cdp_tleft: cdp_tright);
break;
case CDS_END: /* end state */
if (ch6_qconn (CH_A, U_CDP)) { /* if cdp still conn */
cdp_sta = CDS_INIT; /* return to init */
sim_activate (uptr, 1); /* next card */
}
break;
}
return SCPE_OK;
}
/* Card end - write card image to file, transition to end state */
t_stat cdp_card_end (UNIT *uptr)
{
uint32 i, col, row, bufw, colbin;
char *pch, bcd, cdp_cbuf[(2 * CD_CHRLNT) + 1];
t_uint64 dat;
if ((uptr->flags & UNIT_ATT) == 0) return SCPE_UNATT; /* not attached? */
if (uptr->flags & UNIT_PCA) pch = bcd_to_ascii_a;
else pch = bcd_to_ascii_h;
for (col = 0; col < ((2 * CD_CHRLNT) + 1); col++)
cdp_cbuf[col] = ' '; /* clear char buf */
for (col = 0; col < 72; col++) { /* process 72 columns */
colbin = 0;
dat = bit_masks[35 - (col % 36)]; /* mask for column */
for (row = 0; row < 12; row++) { /* proc 12 rows */
bufw = (row * 2) + (col / 36); /* index to buffer */
if (cdp_bbuf[bufw] & dat) colbin |= col_masks[row];
}
if (cdp_unit.flags & UNIT_CBN) { /* column binary? */
cdp_cbuf[2 * col] = pch[(colbin >> 6) & 077];
cdp_cbuf[(2 * col) + 1] = pch[colbin & 077];
}
else { /* text */
bcd = colbin_to_bcd (colbin); /* column bin -> BCD */
cdp_cbuf[col] = pch[bcd]; /* -> ASCII */
}
}
for (i = ((2 * CD_CHRLNT) + 1); (i > 0) &&
(cdp_cbuf[i - 1] == ' '); --i) ; /* trim spaces */
cdp_cbuf[i++] = '\n'; /* append nl */
fxwrite (cdp_cbuf, 1, i, uptr->fileref); /* write card */
if (ferror (uptr->fileref)) { /* error? */
perror ("CDP I/O error");
clearerr (uptr->fileref);
return SCPE_IOERR;
}
uptr->pos = ftell (uptr->fileref); /* update position */
cdp_sta = CDS_END; /* end state */
sim_cancel (uptr); /* cancel current */
sim_activate (uptr, cdp_tstop); /* long timer */
return SCPE_OK;
}
/* Card punch reset */
t_stat cdp_reset (DEVICE *dptr)
{
uint32 i;
for (i = 0; i < 24; i++) cdp_bbuf[i] = 0; /* clear buffer */
cdp_sta = 0; /* clear state */
cdp_bptr = 0; /* clear buf ptr */
cdp_chob = 0;
cdp_chob_v = 0;
sim_cancel (&cdp_unit); /* stop punch */
return SCPE_OK;
}
/* Column binary to BCD
This is based on documentation in the IBM 1620 manual and may not be
accurate for the 7094. Each row (12,11,0,1..9) is interpreted as a bit
pattern, and the appropriate bits are set. (Double punches inclusive
OR, eg, 1,8,9 is 9.) On the 1620, double punch errors are detected;
since the 7094 only reads column binary, double punches are ignored.
Bit order, left to right, is 12, 11, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9.
The for loop works right to left, so the table is reversed. */
static const char row_val[12] = {
011, 010, 007, 006, 005, 004,
003, 002, 001, 020, 040, 060
};
char colbin_to_bcd (uint32 cb)
{
uint32 i;
char bcd;
for (i = 0, bcd = 0; i < 12; i++) { /* 'sum' rows */
if (cb & (1 << i)) bcd |= row_val[i];
}
return bcd;
}

124
I7094/i7094_clk.c Normal file
View file

@ -0,0 +1,124 @@
/* i7094_clk.c: IBM 7094 clock
Copyright (c) 2003-2006, 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.
clk RPQ F89349 interval timer
Chronolog calendar clock
*/
#include "i7094_defs.h"
#include <time.h>
uint32 chtr_clk = 0;
extern t_uint64 *M;
t_stat clk_svc (UNIT *uptr);
t_stat clk_reset (DEVICE *dptr);
uint8 bcd_2d (uint32 n, uint8 *b2);
/* CLK data structures
clk_dev CLK device descriptor
clk_unit CLK unit
clk_reg CLK register list
*/
UNIT clk_unit = { UDATA (&clk_svc, 0, 0), 16000 };
REG clk_reg[] = {
{ FLDATA (TRAP, chtr_clk, 0) },
{ DRDATA (TIME, clk_unit.wait, 24), REG_NZ + PV_LEFT },
{ NULL }
};
DEVICE clk_dev = {
"CLK", &clk_unit, clk_reg, NULL,
1, 0, 0, 0, 0, 0,
NULL, NULL, &clk_reset,
NULL, NULL, NULL,
NULL, DEV_DISABLE+DEV_DIS
};
/* Clock unit service */
t_stat clk_svc (UNIT *uptr)
{
t_uint64 ctr;
if ((clk_dev.flags & DEV_DIS) == 0) { /* clock enabled? */
ctr = ReadP (CLK_CTR);
ctr = (ctr + 1) & DMASK; /* increment */
WriteP (CLK_CTR, ctr);
if ((ctr & MMASK) == 0) chtr_clk = 1; /* overflow? req trap */
sim_activate (uptr, sim_rtcn_calb (CLK_TPS, TMR_CLK)); /* reactivate unit */
}
return SCPE_OK;
}
/* Chronolog clock */
uint32 chrono_rd (uint8 *buf, uint32 bufsiz)
{
time_t curtim;
t_uint64 ctr;
struct tm *tptr;
if (bufsiz < 12) return 0;
curtim = time (NULL); /* get time */
tptr = localtime (&curtim); /* decompose */
if (tptr == NULL) return 0; /* error? */
buf[0] = bcd_2d (tptr->tm_mon + 1, buf + 1);
buf[2] = bcd_2d (tptr->tm_mday, buf + 3);
buf[4] = bcd_2d (tptr->tm_hour, buf + 5);
buf[6] = bcd_2d (tptr->tm_min, buf + 7);
buf[8] = bcd_2d (tptr->tm_sec, buf + 9);
ctr = ReadP (CLK_CTR);
buf[10] = bcd_2d ((uint32) (ctr % 60), buf + 11);
return 12;
}
/* Convert number (0-99) to BCD */
uint8 bcd_2d (uint32 n, uint8 *b2)
{
uint8 d1, d2;
d1 = n / 10;
d2 = n % 10;
if (d1 == 0) d1 = BCD_ZERO;
if (d2 == 0) d2 = BCD_ZERO;
if (b2 != NULL) *b2 = d2;
return d1;
}
/* Reset routine */
t_stat clk_reset (DEVICE *dptr)
{
chtr_clk = 0;
if (clk_dev.flags & DEV_DIS) sim_cancel (&clk_unit);
else sim_activate (&clk_unit, sim_rtcn_init (clk_unit.wait, TMR_CLK));
return SCPE_OK;
}

1149
I7094/i7094_com.c Normal file

File diff suppressed because it is too large Load diff

2239
I7094/i7094_cpu.c Normal file

File diff suppressed because it is too large Load diff

837
I7094/i7094_cpu1.c Normal file
View file

@ -0,0 +1,837 @@
/* i7094_cpu1.c: IBM 7094 CPU complex instructions
Copyright (c) 2003-2006, 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.
*/
#include "i7094_defs.h"
#define FP_HIFRAC(x) ((uint32) ((x) >> FP_N_FR) & FP_FMASK)
#define FP_LOFRAC(x) ((uint32) (x) & FP_FMASK)
#define FP_PACK38(s,e,f) (((s)? AC_S: 0) | ((t_uint64) (f)) | \
(((t_uint64) ((e) & FP_M_ACCH)) << FP_V_CH))
#define FP_PACK36(s,e,f) (((s)? SIGN: 0) | ((t_uint64) (f)) | \
(((t_uint64) ((e) & FP_M_CH)) << FP_V_CH))
extern t_uint64 AC, MQ, SI, KEYS;
extern uint32 PC;
extern uint32 SLT, SSW;
extern uint32 cpu_model, stop_illop;
extern uint32 ind_ovf, ind_dvc, ind_ioc, ind_mqo;
extern uint32 mode_ttrap, mode_strap, mode_ctrap, mode_ftrap;
extern uint32 mode_storn, mode_multi;
extern uint32 chtr_pend, chtr_inht, chtr_inhi;
extern uint32 ch_flags[NUM_CHAN];
typedef struct { /* unpacked fp */
uint32 s; /* sign: 0 +, 1 - */
int32 ch; /* exponent */
t_uint64 fr; /* fraction (54b) */
} UFP;
uint32 op_frnd (void);
t_uint64 fp_fracdiv (t_uint64 dvd, t_uint64 dvr, t_uint64 *rem);
void fp_norm (UFP *op);
void fp_unpack (t_uint64 h, t_uint64 l, t_bool q_ac, UFP *op);
uint32 fp_pack (UFP *op, uint32 mqs, int32 mqch);
extern t_bool fp_trap (uint32 spill);
extern t_bool sel_trap (uint32 va);
extern t_stat ch_op_reset (uint32 ch, t_bool ch7909);
/* Integer add
Sherman: "As the result of an addition or subtraction, if the C(AC) is
zero, the sign of AC is unchanged." */
void op_add (t_uint64 op)
{
t_uint64 mac = AC & AC_MMASK; /* get magnitudes */
t_uint64 mop = op & MMASK;
AC = AC & AC_S; /* isolate AC sign */
if ((AC? 1: 0) ^ ((op & SIGN)? 1: 0)) { /* signs diff? sub */
if (mac >= mop) AC = AC | (mac - mop); /* AC >= MQ */
else AC = (AC ^ AC_S) | (mop - mac); /* <, sign change */
}
else {
AC = AC | ((mac + mop) & AC_MMASK); /* signs same, add */
if ((AC ^ mac) & AC_P) ind_ovf = 1; /* P change? overflow */
}
return;
}
/* Multiply */
void op_mpy (t_uint64 ac, t_uint64 sr, uint32 sc)
{
uint32 sign;
if (sc == 0) return; /* sc = 0? nop */
sign = ((MQ & SIGN)? 1: 0) ^ ((sr & SIGN)? 1: 0); /* result sign */
ac = ac & AC_MMASK; /* clear AC sign */
sr = sr & MMASK; /* mpy magnitude */
MQ = MQ & MMASK; /* MQ magnitude */
if (sr && MQ) { /* mpy != 0? */
while (sc--) { /* for sc */
if (MQ & 1) ac = (ac + sr) & AC_MMASK; /* MQ35? AC += mpy */
MQ = (MQ >> 1) | ((ac & 1) << 34); /* AC'MQ >> 1 */
ac = ac >> 1;
}
}
else ac = MQ = 0; /* result = 0 */
if (sign) { /* negative? */
ac = ac | AC_S; /* insert signs */
MQ = MQ | SIGN;
}
AC = ac; /* update AC */
return;
}
/* Divide */
t_bool op_div (t_uint64 sr, uint32 sc)
{
uint32 signa, signm;
if (sc == 0) return FALSE; /* sc = 0? nop */
signa = (AC & AC_S)? 1: 0; /* get signs */
signm = (sr & SIGN)? 1: 0;
sr = sr & MMASK; /* get dvr magn */
if ((AC & AC_MMASK) >= sr) return TRUE; /* |AC| >= |sr|? */
AC = AC & AC_MMASK; /* AC, MQ magn */
MQ = MQ & MMASK;
while (sc--) { /* for sc */
AC = ((AC << 1) & AC_MMASK) | (MQ >> 34); /* AC'MQ << 1 */
MQ = (MQ << 1) & MMASK;
if (AC >= sr) { /* AC >= dvr? */
AC = AC - sr; /* AC -= dvr */
MQ = MQ | 1; /* set quo bit */
}
}
if (signa ^ signm) MQ = MQ | SIGN; /* quo neg? */
if (signa) AC = AC | AC_S; /* rem neg? */
return FALSE; /* div ok */
}
/* Shifts */
void op_als (uint32 addr)
{
uint32 sc = addr & SCMASK;
if ((sc >= 35)? /* shift >= 35? */
((AC & MMASK) != 0): /* test all bits for ovf */
(((AC & MMASK) >> (35 - sc)) != 0)) /* test only 35-sc bits */
ind_ovf = 1;
if (sc >= 37) AC = AC & AC_S; /* sc >= 37? result 0 */
else AC = (AC & AC_S) | ((AC << sc) & AC_MMASK); /* shift, save sign */
return;
}
void op_ars (uint32 addr)
{
uint32 sc = addr & SCMASK;
if (sc >= 37) AC = AC & AC_S; /* sc >= 37? result 0 */
else AC = (AC & AC_S) | ((AC & AC_MMASK) >> sc); /* shift, save sign */
return;
}
void op_lls (uint32 addr)
{
uint32 sc; /* get sc */
AC = AC & AC_MMASK; /* clear AC sign */
for (sc = addr & SCMASK; sc != 0; sc--) { /* for SC */
AC = ((AC << 1) & AC_MMASK) | ((MQ >> 34) & 1); /* AC'MQ << 1 */
MQ = (MQ & SIGN) | ((MQ << 1) & MMASK); /* preserve MQ sign */
if (AC & AC_P) ind_ovf = 1; /* if P, overflow */
}
if (MQ & SIGN) AC = AC | AC_S; /* set ACS from MQS */
return;
}
void op_lrs (uint32 addr)
{
uint32 sc = addr & SCMASK;
t_uint64 mac;
MQ = MQ & MMASK; /* get MQ magnitude */
if (sc != 0) {
mac = AC & AC_MMASK; /* get AC magnitude, */
AC = AC & AC_S; /* sign */
if (sc < 35) { /* sc [1,34]? */
MQ = ((MQ >> sc) | (mac << (35 - sc))) & MMASK; /* MQ has AC'MQ */
AC = AC | (mac >> sc); /* AC has AC only */
}
else if (sc < 37) { /* sc [35:36]? */
MQ = (mac >> (sc - 35)) & MMASK; /* MQ has AC only */
AC = AC | (mac >> sc); /* AC has <QP> */
}
else if (sc < 72) /* sc [37:71]? */
MQ = (mac >> (sc - 35)) & MMASK; /* MQ has AC only */
else MQ = 0; /* >72? MQ = 0 */
}
if (AC & AC_S) MQ = MQ | SIGN; /* set MQS from ACS */
return;
}
void op_lgl (uint32 addr)
{
uint32 sc; /* get sc */
for (sc = addr & SCMASK; sc != 0; sc--) { /* for SC */
AC = (AC & AC_S) | ((AC << 1) & AC_MMASK) | /* AC'MQ << 1 */
((MQ >> 35) & 1); /* preserve AC sign */
MQ = (MQ << 1) & DMASK;
if (AC & AC_P) ind_ovf = 1; /* if P, overflow */
}
return;
}
void op_lgr (uint32 addr)
{
uint32 sc = addr & SCMASK;
t_uint64 mac;
if (sc != 0) {
mac = AC & AC_MMASK; /* get AC magnitude, */
AC = AC & AC_S; /* sign */
if (sc < 36) { /* sc [1,35]? */
MQ = ((MQ >> sc) | (mac << (36 - sc))) & DMASK; /* MQ has AC'MQ */
AC = AC | (mac >> sc); /* AC has AC only */
}
else if (sc == 36) { /* sc [36]? */
MQ = mac & DMASK; /* MQ = AC<P,1:35> */
AC = AC | (mac >> 36); /* AC = AC<Q> */
}
else if (sc < 73) /* sc [37, 72]? */
MQ = (mac >> (sc - 36)) & DMASK; /* MQ has AC only */
else MQ = 0; /* >72, AC,MQ = 0 */
}
return;
}
/* Plus sense - undefined operations are NOPs */
t_stat op_pse (uint32 addr)
{
uint32 ch, spill;
switch (addr) {
case 00000: /* CLM */
if (cpu_model & I_9X) AC = AC & AC_S; /* 709X only */
break;
case 00001: /* LBT */
if ((AC & 1) != 0) PC = (PC + 1) & AMASK;
break;
case 00002: /* CHS */
AC = AC ^ AC_S;
break;
case 00003: /* SSP */
AC = AC & ~AC_S;
break;
case 00004: /* ENK */
MQ = KEYS;
break;
case 00005: /* IOT */
if (ind_ioc) ind_ioc = 0;
else PC = (PC + 1) & AMASK;
break;
case 00006: /* COM */
AC = AC ^ AC_MMASK;
break;
case 00007: /* ETM */
if (cpu_model & I_9X) mode_ttrap = 1; /* 709X only */
break;
case 00010: /* RND */
if ((cpu_model & I_9X) && (MQ & B1)) /* 709X only, MQ1 set? */
op_add ((t_uint64) 1); /* incr AC */
break;
case 00011: /* FRN */
if (cpu_model & I_9X) { /* 709X only */
spill = op_frnd ();
if (spill) fp_trap (spill);
}
break;
case 00012: /* DCT */
if (ind_dvc) ind_dvc = 0;
else PC = (PC + 1) & AMASK;
break;
case 00014: /* RCT */
chtr_inhi = 1; /* 1 cycle delay */
chtr_inht = 0; /* clr inhibit trap */
chtr_pend = 0; /* no trap now */
break;
case 00016: /* LMTM */
if (cpu_model & I_94) mode_multi = 0; /* 709X only */
break;
case 00140: /* SLF */
if (cpu_model & I_9X) SLT = 0; /* 709X only */
break;
case 00141: case 00142: case 00143: case 00144: /* SLN */
if (cpu_model & I_9X) /* 709X only */
SLT = SLT | (1u << (00144 - addr));
break;
case 00161: case 00162: case 00163: /* SWT */
case 00164: case 00165: case 00166:
if ((SSW & (1u << (00166 - addr))) != 0)
PC = (PC + 1) & AMASK;
break;
case 01000: case 02000: case 03000: case 04000: /* BTT */
case 05000: case 06000: case 07000: case 10000:
if (cpu_model & I_9X) { /* 709X only */
if (sel_trap (PC)) break; /* sel trap? */
ch = GET_U_CH (addr); /* get channel */
if (ch_flags[ch] & CHF_BOT) /* BOT? */
ch_flags[ch] &= ~CHF_BOT; /* clear */
else PC = (PC + 1) & AMASK; /* else skip */
}
break;
case 001350: case 002350: case 003350: case 004350: /* RICx */
case 005350: case 006350: case 007350: case 010350:
ch = GET_U_CH (addr); /* get channel */
return ch_op_reset (ch, 1);
case 001352: case 002352: case 003352: case 004352: /* RDCx */
case 005352: case 006352: case 007352: case 010352:
ch = GET_U_CH (addr); /* get channel */
return ch_op_reset (ch, 0);
} /* end case */
return SCPE_OK;
}
/* Minus sense */
t_stat op_mse (uint32 addr)
{
uint32 t, ch;
switch (addr) {
case 00000: /* CLM */
if (cpu_model & I_9X) AC = AC & AC_S; /* 709X only */
break;
case 00001: /* PBT */
if ((AC & AC_P) != 0) PC = (PC + 1) & AMASK;
break;
case 00002: /* EFTM */
if (cpu_model & I_9X) { /* 709X only */
mode_ftrap = 1;
ind_mqo = 0; /* clears MQ ovf */
}
break;
case 00003: /* SSM */
if (cpu_model & I_9X) AC = AC | AC_S; /* 709X only */
break;
case 00004: /* LFTM */
if (cpu_model & I_9X) mode_ftrap = 0; /* 709X only */
break;
case 00005: /* ESTM */
if (cpu_model & I_9X) mode_strap = 1; /* 709X only */
break;
case 00006: /* ECTM */
if (cpu_model & I_9X) mode_ctrap = 1; /* 709X only */
break;
case 00007: /* LTM */
if (cpu_model & I_9X) mode_ttrap = 0; /* 709X only */
break;
case 00010: /* LSNM */
if (cpu_model & I_9X) mode_storn = 0; /* 709X only */
break;
case 00012: /* RTT (704) */
if (cpu_model & I_9X) sel_trap (PC); /* 709X only */
break;
case 00016: /* EMTM */
mode_multi = 1;
break;
case 00140: /* SLF */
if (cpu_model & I_9X) SLT = 0; /* 709X only */
break;
case 00141: case 00142: case 00143: case 00144: /* SLT */
if (cpu_model & I_9X) { /* 709X only */
t = SLT & (1u << (00144 - addr));
SLT = SLT & ~t;
if (t != 0) PC = (PC + 1) & AMASK;
}
break;
case 00161: case 00162: case 00163: /* SWT */
case 00164: case 00165: case 00166:
if ((cpu_model & I_9X) && /* 709X only */
((SSW & (1u << (00166 - addr))) != 0))
PC = (PC + 1) & AMASK;
break;
case 001000: case 002000: case 003000: case 004000: /* ETT */
case 005000: case 006000: case 007000: case 010000:
if (sel_trap (PC)) break; /* sel trap? */
ch = GET_U_CH (addr); /* get channel */
if (ch_flags[ch] & CHF_EOT) /* EOT? */
ch_flags[ch] = ch_flags[ch] & ~CHF_EOT; /* clear */
else PC = (PC + 1) & AMASK; /* else skip */
break;
}
return SCPE_OK;
}
/* Floating add
Notes:
- AC<Q,P> enter into the initial exponent comparison. If either is set,
the numbers are always swapped. AC<P> gets OR'd into AC<S> during the
swap, and AC<Q,P> are cleared afterwards
- The early end test is actually > 077 if AC <= SR and > 100 if
AC > SR. However, any shift >= 54 will produce a zero fraction,
so the difference can be ignored */
uint32 op_fad (t_uint64 sr, t_bool norm)
{
UFP op1, op2, t;
int32 mqch, diff;
MQ = 0; /* clear MQ */
fp_unpack (AC, 0, 1, &op1); /* unpack AC */
fp_unpack (sr, 0, 0, &op2); /* unpack sr */
if (op1.ch > op2.ch) { /* AC exp > SR exp? */
if (AC & AC_P) op1.s = 1; /* AC P or's with S */
t = op1; /* swap operands */
op1 = op2;
op2 = t;
op2.ch = op2.ch & FP_M_CH; /* clear P,Q */
}
diff = op2.ch - op1.ch; /* exp diff */
if (diff) { /* any shift? */
if ((diff < 0) || (diff > 077)) op1.fr = 0; /* diff > 63? */
else op1.fr = op1.fr >> diff; /* no, denormalize */
}
if (op1.s ^ op2.s) { /* subtract? */
if (op1.fr >= op2.fr) { /* op1 > op2? */
op2.fr = op1.fr - op2.fr; /* op1 - op2 */
op2.s = op1.s; /* op2 sign is result */
}
else op2.fr = op2.fr - op1.fr; /* else op2 - op1 */
}
else {
op2.fr = op2.fr + op1.fr; /* op2 + op1 */
if (op2.fr & FP_FCRY) { /* carry? */
op2.fr = op2.fr >> 1; /* renormalize */
op2.ch++; /* incr exp */
}
}
if (norm) { /* normalize? */
if (op2.fr) { /* non-zero frac? */
fp_norm (&op2);
mqch = op2.ch - FP_N_FR;
}
else op2.ch = mqch = 0; /* else true zero */
}
else mqch = op2.ch - FP_N_FR;
return fp_pack (&op2, op2.s, mqch); /* pack AC, MQ */
}
/* Floating multiply */
uint32 op_fmp (t_uint64 sr, t_bool norm)
{
UFP op1, op2;
int32 mqch;
uint32 f1h, f2h;
fp_unpack (MQ, 0, 0, &op1); /* unpack MQ */
fp_unpack (sr, 0, 0, &op2); /* unpack sr */
op1.s = op1.s ^ op2.s; /* result sign */
if ((op2.ch == 0) && (op2.fr == 0)) { /* sr a normal 0? */
AC = op1.s? AC_S: 0; /* result is 0 */
MQ = op1.s? SIGN: 0;
return 0;
}
f1h = FP_HIFRAC (op1.fr); /* get hi fracs */
f2h = FP_HIFRAC (op2.fr);
op1.fr = ((t_uint64) f1h) * ((t_uint64) f2h); /* f1h * f2h */
op1.ch = (op1.ch & FP_M_CH) + op2.ch - FP_BIAS; /* result exponent */
if (norm) { /* normalize? */
if (!(op1.fr & FP_FNORM)) { /* not normalized? */
op1.fr = op1.fr << 1; /* shift frac left 1 */
op1.ch--; /* decr exp */
}
if (FP_HIFRAC (op1.fr)) /* hi result non-zero? */
mqch = op1.ch - FP_N_FR; /* set MQ exp */
else op1.ch = mqch = 0; /* clear AC, MQ exp */
}
else mqch = op1.ch - FP_N_FR; /* set MQ exp */
return fp_pack (&op1, op1.s, mqch); /* pack AC, MQ */
}
/* Floating divide */
uint32 op_fdv (t_uint64 sr)
{
UFP op1, op2;
int32 mqch;
uint32 spill, quos;
t_uint64 rem;
fp_unpack (AC, 0, 1, &op1); /* unpack AC */
fp_unpack (sr, 0, 0, &op2); /* unpack sr */
quos = op1.s ^ op2.s; /* quotient sign */
if (op1.fr >= (2 * op2.fr)) { /* |AC| >= 2*|sr|? */
MQ = quos? SIGN: 0; /* MQ = sign only */
return TRAP_F_DVC; /* divide check */
}
if (op1.fr == 0) { /* |AC| == 0? */
MQ = quos? SIGN: 0; /* MQ = sign only */
AC = 0; /* AC = +0 */
return 0; /* done */
}
op1.ch = op1.ch & FP_M_CH; /* remove AC<Q,P> */
if (op1.fr >= op2.fr) { /* |AC| >= |sr|? */
op1.fr = op1.fr >> 1; /* denorm AC */
op1.ch++;
}
op1.fr = fp_fracdiv (op1.fr, op2.fr, &rem); /* fraction divide */
op1.fr = op1.fr | (rem << FP_N_FR); /* rem'quo */
mqch = op1.ch - op2.ch + FP_BIAS; /* quotient exp */
op1.ch = op1.ch - FP_N_FR; /* remainder exp */
spill = fp_pack (&op1, quos, mqch); /* pack up */
return (spill? (spill | TRAP_F_SGL): 0); /* if spill, set SGL */
}
/* Double floating add
Notes:
- AC<Q,P> enter into the initial exponent comparison. If either is set,
the numbers are always swapped. AC<P> gets OR'd into AC<S> during the
swap, and AC<Q,P> are cleared afterwards
- For most cases, SI ends up with the high order part of the larger number
- The 'early end' cases (smaller number is shifted away) must be tracked
exactly for SI impacts. The early end cases are:
(a) AC > SR, diff > 0100, and AC normalized
(b) AC <= SR, diff > 077, and SR normalized
In case (a), SI is unchanged. In case (b), SI ends up with the SR sign
and characteristic but the MQ (!) fraction */
uint32 op_dfad (t_uint64 sr, t_uint64 sr1, t_bool norm)
{
UFP op1, op2, t;
int32 mqch, diff;
fp_unpack (AC, MQ, 1, &op1); /* unpack AC'MQ */
fp_unpack (sr, sr1, 0, &op2); /* unpack sr'sr1 */
if (op1.ch > op2.ch) { /* AC exp > SR exp? */
if (((op1.ch - op2.ch) > 0100) && (AC & B9)) ; /* early out */
else SI = FP_PACK36 (op1.s, op1.ch, FP_HIFRAC (op1.fr));
if (AC & AC_P) op1.s = 1; /* AC P or's with S */
t = op1; /* swap operands */
op1 = op2;
op2 = t;
op2.ch = op2.ch & FP_M_CH; /* clear P,Q */
}
else { /* AC <= SR */
if (((op2.ch - op1.ch) > 077) && (sr & B9)) /* early out */
SI = FP_PACK36 (op2.s, op2.ch, FP_LOFRAC (MQ));
else SI = FP_PACK36 (op2.s, op2.ch, FP_HIFRAC (op2.fr));
}
diff = op2.ch - op1.ch; /* exp diff */
if (diff) { /* any shift? */
if ((diff < 0) || (diff > 077)) op1.fr = 0; /* diff > 63? */
else op1.fr = op1.fr >> diff; /* no, denormalize */
}
if (op1.s ^ op2.s) { /* subtract? */
if (op1.fr >= op2.fr) { /* op1 > op2? */
op2.fr = op1.fr - op2.fr; /* op1 - op2 */
op2.s = op1.s; /* op2 sign is result */
}
else op2.fr = op2.fr - op1.fr; /* op2 - op1 */
}
else {
op2.fr = op2.fr + op1.fr; /* op2 + op1 */
if (op2.fr & FP_FCRY) { /* carry? */
op2.fr = op2.fr >> 1; /* renormalize */
op2.ch++; /* incr exp */
}
}
if (norm) { /* normalize? */
if (op2.fr) { /* non-zero frac? */
fp_norm (&op2);
mqch = op2.ch - FP_N_FR;
}
else op2.ch = mqch = 0; /* else true zero */
}
else mqch = op2.ch - FP_N_FR;
return fp_pack (&op2, op2.s, mqch); /* pack AC, MQ */
}
/* Double floating multiply
Notes (notation is A+B' * C+D', where ' denotes 2^-27):
- The instruction returns 0 if A and C are both zero, because B*D is never
done as part of the algorithm
- For most cases, SI ends up with B*C, with a zero sign and exponent
- For the A+B' both zero 'early end' case SI ends up with A or C,
depending on whether the operation is normalized or not */
uint32 op_dfmp (t_uint64 sr, t_uint64 sr1, t_bool norm)
{
UFP op1, op2;
int32 mqch;
uint32 f1h, f2h, f1l, f2l;
t_uint64 tx;
fp_unpack (AC, MQ, 1, &op1); /* unpack AC'MQ */
fp_unpack (sr, sr1, 0, &op2); /* unpack sr'sr1 */
op1.s = op1.s ^ op2.s; /* result sign */
f1h = FP_HIFRAC (op1.fr); /* A */
f1l = FP_LOFRAC (op1.fr); /* B */
f2h = FP_HIFRAC (op2.fr); /* C */
f2l = FP_LOFRAC (op2.fr); /* D */
if (((op1.ch == 0) && (op1.fr == 0)) || /* AC'MQ normal 0? */
((op2.ch == 0) && (op2.fr == 0)) || /* sr'sr1 normal 0? */
((f1h == 0) && (f2h == 0))) { /* both hi frac zero? */
AC = op1.s? AC_S: 0; /* result is 0 */
MQ = op1.s? SIGN: 0;
SI = sr; /* SI has C */
return 0;
}
op1.ch = (op1.ch & FP_M_CH) + op2.ch - FP_BIAS; /* result exponent */
if (op1.fr) { /* A'B != 0? */
op1.fr = ((t_uint64) f1h) * ((t_uint64) f2h); /* A * C */
tx = ((t_uint64) f1h) * ((t_uint64) f2l); /* A * D */
op1.fr = op1.fr + (tx >> FP_N_FR); /* add in hi 27b */
tx = ((t_uint64) f1l) * ((t_uint64) f2h); /* B * C */
op1.fr = op1.fr + (tx >> FP_N_FR); /* add in hi 27b */
SI = tx >> FP_N_FR; /* SI keeps B * C */
}
else {
if (norm) SI = sr; /* early out */
else SI = FP_PACK36 (op2.s, op2.ch, 0);
}
if (norm) { /* normalize? */
if (!(op1.fr & FP_FNORM)) { /* not normalized? */
op1.fr = op1.fr << 1; /* shift frac left 1 */
op1.ch--; /* decr exp */
}
if (FP_HIFRAC (op1.fr)) { /* non-zero? */
mqch = op1.ch - FP_N_FR; /* set MQ exp */
}
else op1.ch = mqch = 0; /* clear AC, MQ exp */
}
else mqch = op1.ch - FP_N_FR; /* set MQ exp */
return fp_pack (&op1, op1.s, mqch); /* pack AC, MQ */
}
/* Double floating divide
Notes:
- This is a Taylor series expansion (where ' denotes >> 27):
(A+B') * (C+D')^-1 = (A+B') * C^-1 - (A+B') * D'* C^-2 +...
to two terms, which can be rewritten as terms Q1, Q2:
Q1 = (A+B')/C
Q2' = (R - Q1*D)'/C
- Tracking the sign of Q2' is complicated:
Q1 has the sign of the quotient, s_AC ^ s_SR
D has the sign of the divisor, s_SR
R has the sign of the dividend, s_AC
Q1*D sign is s_AC ^ s_SR ^ s^SR = s^AC
Therefore, R and Q1*D have the same sign, s_AC
Q2' sign is s^AC ^ s_SR, which is the sign of the quotient
- For first divide check, SI is 0
- For other cases, including second divide check, SI ends up with Q1
- R-Q1*D is only calculated to the high 27b; using the full 54b
throws off the result
- The second divide must check for divd >= divr, otherwise an extra
bit of quotient would be devloped, throwing off the result
- A late ECO added full post-normalization; single precision divide
does no normalization */
uint32 op_dfdv (t_uint64 sr, t_uint64 sr1)
{
UFP op1, op2;
int32 mqch;
uint32 csign, ac_s;
t_uint64 f1h, f2h, tr, tq1, tq1d, trmq1d, tq2;
fp_unpack (AC, MQ, 1, &op1); /* unpack AC'MQ */
fp_unpack (sr, 0, 0, &op2); /* unpack sr only */
ac_s = op1.s; /* save AC sign */
op1.s = op1.s ^ op2.s; /* sign of result */
f1h = FP_HIFRAC (op1.fr);
f2h = FP_HIFRAC (op2.fr);
if (f1h >= (2 * f2h)) { /* |A| >= 2*|C|? */
SI = 0; /* clear SI */
return TRAP_F_DVC; /* divide check */
}
if (f1h == 0) { /* |AC| == 0? */
SI = MQ = op1.s? SIGN: 0; /* MQ, SI = sign only */
AC = op1.s? AC_S: 0; /* AC = sign only */
return 0; /* done */
}
op1.ch = op1.ch & FP_M_CH; /* remove AC<Q,P> */
if (f1h >= f2h) { /* |A| >= |C|? */
op1.fr = op1.fr >> 1; /* denorm AC */
op1.ch++;
}
op1.ch = op1.ch - op2.ch + FP_BIAS; /* exp of quotient */
tq1 = fp_fracdiv (op1.fr, op2.fr, &tr); /* |A+B| / |C| */
tr = tr << FP_N_FR; /* R << 27 */
tq1d = (tq1 * ((t_uint64) FP_LOFRAC (sr1))) & /* Q1 * D */
~((t_uint64) FP_FMASK); /* top 27 bits */
csign = (tr < tq1d); /* correction sign */
if (csign) trmq1d = tq1d - tr; /* |R|<|Q1*D|? compl */
else trmq1d = tr - tq1d; /* no, subtr ok */
SI = FP_PACK36 (op1.s, op1.ch, tq1); /* SI has Q1 */
if (trmq1d >= (2 * op2.fr)) { /* |R-Q1*D| >= 2*|C|? */
AC = FP_PACK38 (csign ^ ac_s, 0, FP_HIFRAC (trmq1d)); /* AC has R-Q1*D */
MQ = (csign ^ ac_s)? SIGN: 0; /* MQ = sign only */
return TRAP_F_DVC; /* divide check */
}
tq2 = fp_fracdiv (trmq1d, op2.fr, NULL); /* |R-Q1*D| / |C| */
if (trmq1d >= op2.fr) tq2 &= ~((t_uint64) 1); /* can only gen 27b quo */
op1.fr = tq1 << FP_N_FR; /* shift Q1 into place */
if (csign) op1.fr = op1.fr - tq2; /* sub or add Q2 */
else op1.fr = op1.fr + tq2;
fp_norm (&op1); /* normalize */
if (op1.fr) mqch = op1.ch - FP_N_FR; /* non-zero? */
else op1.ch = mqch = 0; /* clear AC, MQ exp */
return fp_pack (&op1, op1.s, mqch); /* pack AC, MQ */
}
/* Floating round */
uint32 op_frnd (void)
{
UFP op;
uint32 spill;
spill = 0; /* no error */
if (MQ & B9) { /* MQ9 set? */
fp_unpack (AC, 0, 1, &op); /* unpack AC */
op.fr = op.fr + ((t_uint64) (1 << FP_N_FR)); /* round up */
if (op.fr & FP_FCRY) { /* carry out? */
op.fr = op.fr >> 1; /* renormalize */
op.ch++; /* incr exp */
if (op.ch == (FP_M_CH + 1)) /* ovf with QP = 0? */
spill = TRAP_F_OVF | TRAP_F_AC;
}
AC = FP_PACK38 (op.s, op.ch, FP_HIFRAC (op.fr)); /* pack AC */
}
return spill;
}
/* Fraction divide - 54/27'0 yielding quotient and remainder */
t_uint64 fp_fracdiv (t_uint64 dvd, t_uint64 dvr, t_uint64 *rem)
{
dvr = dvr >> FP_N_FR;
if (rem) *rem = dvd % dvr;
return (dvd / dvr);
}
/* Floating point normalize */
void fp_norm (UFP *op)
{
op->fr = op->fr & FP_DFMASK; /* mask fraction */
if (op->fr == 0) return; /* zero? */
while ((op->fr & FP_FNORM) == 0) { /* until norm */
op->fr = op->fr << 1; /* lsh 1 */
op->ch--; /* decr exp */
}
return;
}
/* Floating point unpack */
void fp_unpack (t_uint64 h, t_uint64 l, t_bool q_ac, UFP *op)
{
if (q_ac) { /* AC? */
op->s = (h & AC_S)? 1: 0; /* get sign */
op->ch = (uint32) ((h >> FP_V_CH) & FP_M_ACCH); /* get exp */
}
else {
op->s = (h & SIGN)? 1: 0; /* no, mem */
op->ch = (uint32) ((h >> FP_V_CH) & FP_M_CH);
}
op->fr = (((t_uint64) FP_LOFRAC (h)) << FP_N_FR) | /* get frac hi */
((t_uint64) FP_LOFRAC (l)); /* get frac lo */
return;
}
/* Floating point pack */
uint32 fp_pack (UFP *op, uint32 mqs, int32 mqch)
{
uint32 spill;
AC = FP_PACK38 (op->s, op->ch, FP_HIFRAC (op->fr)); /* pack AC */
MQ = FP_PACK36 (mqs, mqch, FP_LOFRAC (op->fr)); /* pack MQ */
if (op->ch > FP_M_CH) spill = TRAP_F_OVF | TRAP_F_AC; /* check AC exp */
else if (op->ch < 0) spill = TRAP_F_AC;
else spill = 0;
if (mqch > FP_M_CH) spill |= (TRAP_F_OVF | TRAP_F_MQ); /* check MQ exp */
else if (mqch < 0) spill |= TRAP_F_MQ;
return spill;
}

152
I7094/i7094_dat.h Normal file
View file

@ -0,0 +1,152 @@
/* i7094_dat.h: IBM 7094 data conversion tables
Copyright (c) 2003-2006, 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.
*/
/* Nine-code to ASCII conversion */
const char nine_to_ascii_a[64] = {
'0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', '^', '#', '@', ':', '>', '{',
'&', 'A', 'B', 'C', 'D', 'E', 'F', 'G',
'H', 'I', '?', '.', ')', '[', '<', '}',
'-', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
'Q', 'R', '!', '$', '*', ']', ';', '_',
' ', '/', 'S', 'T', 'U', 'V', 'W', 'X',
'Y', 'Z', '|', ',', '%', '~', '\\', '"',
};
const char nine_to_ascii_h[64] = {
'0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', '^', '=', '\'', ':', '>', '{',
'+', 'A', 'B', 'C', 'D', 'E', 'F', 'G',
'H', 'I', '?', '.', ')', '[', '<', '}',
'-', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
'Q', 'R', '!', '$', '*', ']', ';', '_',
' ', '/', 'S', 'T', 'U', 'V', 'W', 'X',
'Y', 'Z', '|', ',', '(', '~', '\\', '"',
};
/* ASCII to nine-code conversion */
const char ascii_to_nine[128] = {
060, 060, 060, 060, 060, 060, 060, 060, /* 000 - 037 */
060, 060, 060, 060, 060, 060, 060, 060,
060, 060, 060, 060, 060, 060, 060, 060,
060, 060, 060, 060, 060, 060, 060, 060,
060, 052, 077, 013, 053, 074, 020, 014, /* 040 - 077 */
074, 034, 054, 020, 073, 040, 033, 061,
000, 001, 002, 003, 004, 005, 006, 007,
010, 011, 015, 056, 036, 013, 016, 032,
014, 021, 022, 023, 024, 025, 026, 027, /* 100 - 137 */
030, 031, 041, 042, 043, 044, 045, 046,
047, 050, 051, 062, 063, 064, 065, 066,
067, 070, 071, 035, 076, 055, 012, 057,
060, 021, 022, 023, 024, 025, 026, 027, /* 140 - 177 */
030, 031, 041, 042, 043, 044, 045, 046,
047, 050, 051, 062, 063, 064, 065, 066,
067, 070, 071, 017, 072, 037, 075, 060
};
/* ASCII to BCD conversion */
const char ascii_to_bcd[128] = {
000, 000, 000, 000, 000, 000, 000, 000, /* 000 - 037 */
000, 000, 000, 000, 000, 000, 000, 000,
000, 000, 000, 000, 000, 000, 000, 000,
000, 000, 000, 000, 000, 000, 000, 000,
000, 052, 037, 013, 053, 074, 060, 014, /* 040 - 077 */
034, 074, 054, 060, 033, 040, 073, 021,
020, 001, 002, 003, 004, 005, 006, 007,
010, 011, 015, 056, 076, 013, 016, 072,
014, 061, 062, 063, 064, 065, 066, 067, /* 100 - 137 */
070, 071, 041, 042, 043, 044, 045, 046,
047, 050, 051, 022, 023, 024, 025, 026,
027, 030, 031, 075, 036, 055, 012, 057,
000, 061, 062, 063, 064, 065, 066, 067, /* 140 - 177 */
070, 071, 041, 042, 043, 044, 045, 046,
047, 050, 051, 022, 023, 024, 025, 026,
027, 030, 031, 017, 032, 077, 035, 000
};
/* BCD to ASCII conversion */
const char bcd_to_ascii_a[64] = {
' ', '1', '2', '3', '4', '5', '6', '7',
'8', '9', '^', '#', '@', ':', '>', '{',
'0', '/', 'S', 'T', 'U', 'V', 'W', 'X',
'Y', 'Z', '|', ',', '%', '~', '\\', '"',
'-', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
'Q', 'R', '!', '$', '*', ']', ';', '_',
'&', 'A', 'B', 'C', 'D', 'E', 'F', 'G',
'H', 'I', '?', '.', ')', '[', '<', '}'
};
const char bcd_to_ascii_h[64] = {
' ', '1', '2', '3', '4', '5', '6', '7',
'8', '9', '^', '=', '\'', ':', '>', '{',
'0', '/', 'S', 'T', 'U', 'V', 'W', 'X',
'Y', 'Z', '|', ',', '(', '~', '\\', '"',
'-', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
'Q', 'R', '!', '$', '*', ']', ';', '_',
'+', 'A', 'B', 'C', 'D', 'E', 'F', 'G',
'H', 'I', '?', '.', ')', '[', '<', '}'
};
/* BCD to ASCII 48 character print chains */
const char bcd_to_pca[64] = {
' ', '1', '2', '3', '4', '5', '6', '7',
'8', '9', ' ', '#', '@', ' ', ' ', ' ',
'0', '/', 'S', 'T', 'U', 'V', 'W', 'X',
'Y', 'Z', ' ', ',', '%', ' ', ' ', ' ',
'-', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
'Q', 'R', '-', '$', '*', ' ', ' ', ' ',
'&', 'A', 'B', 'C', 'D', 'E', 'F', 'G',
'H', 'I', '&', '.', ')', ' ', ' ', ' '
};
const char bcd_to_pch[64] = {
' ', '1', '2', '3', '4', '5', '6', '7',
'8', '9', ' ', '=', '\'', ' ', ' ', ' ',
'0', '/', 'S', 'T', 'U', 'V', 'W', 'X',
'Y', 'Z', ' ', ',', '(', ' ', ' ', ' ',
'-', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
'Q', 'R', '-', '$', '*', ' ', ' ', ' ',
'&', 'A', 'B', 'C', 'D', 'E', 'F', 'G',
'H', 'I', '&', '.', ')', ' ', ' ', ' '
};
/* BCD to column binary conversion */
const uint32 bcd_to_colbin[64] = {
00000, 00400, 00200, 00100, 00040, 00020, 00010, 00004,
00002, 00001, 00202, 00102, 00042, 00022, 00012, 00006,
01000, 01400, 01200, 01100, 01040, 01020, 01010, 01004,
01002, 01001, 01202, 01102, 01042, 01022, 01012, 01006,
02000, 02400, 02200, 02100, 02040, 02020, 02010, 02004,
02002, 02001, 02202, 02102, 02042, 02022, 02012, 02006,
04000, 04400, 04200, 04100, 04040, 04020, 04010, 04004,
04002, 04001, 04202, 04102, 04042, 04022, 04012, 04006
};

474
I7094/i7094_defs.h Normal file
View file

@ -0,0 +1,474 @@
/* i7094_defs.h: IBM 7094 simulator definitions
Copyright (c) 2003-2006, Robert M Supnik
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Except as contained in this notice, the name of Robert M Supnik shall not be
used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from Robert M Supnik.
This simulator incorporates prior work by Paul Pierce, Dave Pitts, and Rob
Storey. Tom Van Vleck, Stan Dunten, Jerry Saltzer, and other CTSS veterans
helped to reconstruct the CTSS hardware RPQ's. Dave Pitts gets special
thanks for patiently coaching me through IBSYS debug. */
#ifndef _I7094_DEFS_H_
#define _I7094_DEFS_H_ 0
#include "sim_defs.h" /* simulator defns */
/* Simulator stop codes */
#define STOP_HALT 1 /* halted */
#define STOP_IBKPT 2 /* breakpoint */
#define STOP_ILLEG 3 /* illegal instr */
#define STOP_DIVCHK 4 /* divide check */
#define STOP_XEC 5 /* XCT loop */
#define STOP_ASTOP 6 /* address stop */
#define STOP_NXCHN 7 /* nx channel */
#define STOP_7909 8 /* ill inst to 7909 */
#define STOP_NT7909 9 /* ill inst to !7909 */
#define STOP_NXDEV 10 /* nx device */
#define STOP_ILLCHI 11 /* illegal channel op */
#define STOP_WRP 12 /* write protect */
#define STOP_ILLIOP 13 /* illegal I/O op */
#define STOP_INVFMT 14 /* invalid disk format */
#define STOP_NOIFREE 15 /* 7750: no buf for inp */
#define STOP_NOOFREE 16 /* 7750: no buf for out */
#define STOP_INVLIN 17 /* 7750: invalid line# */
#define STOP_INVMSG 18 /* 7750: invalid message */
#define STOP_CHBKPT 19 /* channel breakpoint */
/* Simulator error codes */
#define ERR_STALL 40 /* stall */
#define ERR_ENDRC 41 /* end rec */
#define ERR_NRCF 42 /* no record found */
/* Instruction history - flags in left half of pc entry */
#define HIST_PC 0x04000000 /* CPU */
#define HIST_V_CH 28 /* chan + 1 */
#define HIST_M_CH 0xF
#define HIST_CH(x) (((x) >> HIST_V_CH) & HIST_M_CH)
typedef struct {
uint32 pc;
uint32 ea;
uint32 rpt;
t_uint64 ir;
t_uint64 ac;
t_uint64 mq;
t_uint64 si;
t_uint64 opnd;
} InstHistory;
/* Architectural constants */
#define A704_SIZE 14 /* addr width, 704 mode */
#define ASIZE 15 /* inst addr width */
#define PASIZE 16 /* phys addr width */
#define STDMEMSIZE (1u << ASIZE) /* standard memory */
#define MAXMEMSIZE (1u << PASIZE) /* maximum memory */
#define A704_MASK ((1u << A704_SIZE) - 1)
#define PAMASK ((1u << PASIZE) - 1)
#define MEMSIZE (cpu_unit.capac)
#define BCORE_V (ASIZE) /* (CTSS) A/B core sel */
#define BCORE_BASE (1u << BCORE_V) /* (CTSS) B core base */
/* Traps */
#define TRAP_STD_SAV 000000 /* trap save location */
#define TRAP_TRA_PC 000001 /* trap PC: transfer */
#define TRAP_STR_PC 000002 /* trap PC: STR */
#define TRAP_FP_PC 000010 /* trap PC: flt point */
#define TRAP_PROT_SAV 000032 /* protection trap save */
#define TRAP_PROT_PC 000033 /* protection trap PC */
#define TRAP_704_SAV 040000 /* 704 compat trap */
#define TRAP_SEL_PC 040001 /* 704 trap PC: select */
#define TRAP_CPY_PC 040002 /* 704 trap PC: copy */
#define TRAP_F_MQ 000001 /* MQ error */
#define TRAP_F_AC 000002 /* AC error */
#define TRAP_F_OVF 000004 /* overflow */
#define TRAP_F_SGL 000010 /* single precision */
#define TRAP_F_DVC 000020 /* fake: divide check */
#define TRAP_F_ODD 000040 /* odd address */
#define TRAP_F_BDATA 020000 /* (CTSS) data B core */
#define TRAP_F_BINST 040000 /* (CTSS) inst B core */
/* Integer */
#define DMASK 0777777777777 /* data mask */
#define SIGN 0400000000000 /* sign */
#define MMASK 0377777777777 /* magnitude mask */
#define LMASK 0777777000000 /* left mask */
#define RMASK 0000000777777 /* right mask */
#define PMASK 0700000000000 /* prefix */
#define XMASK 0077777000000 /* decrement */
#define TMASK 0000000700000 /* tag */
#define AMASK 0000000077777 /* address */
#define SCMASK 0000000000377 /* shift count mask */
#define B1 0200000000000 /* bit 1 */
#define B9 0000400000000 /* bit 9 */
/* Accumulator is actually 38b wide */
#define AC_S 02000000000000 /* sign */
#define AC_Q 01000000000000 /* Q */
#define AC_P 00400000000000 /* P */
#define AC_MMASK 01777777777777 /* Q+P+magnitude */
/* Floating point */
#define FP_N_FR 27 /* fraction bits */
#define FP_FMASK ((1u << FP_N_FR) - 1)
#define FP_N_DFR 54 /* double fraction bits */
#define FP_DFMASK ((((t_uint64) 1) << FP_N_DFR) - 1)
#define FP_FNORM (((t_uint64) 1u) << (FP_N_DFR - 1)) /* normalized bit */
#define FP_FCRY (((t_uint64) 1u) << FP_N_DFR) /* fraction carry */
#define FP_BIAS 0200 /* exponent bias */
#define FP_V_CH (FP_N_FR) /* exponent */
#define FP_M_CH 0377 /* SR char mask */
#define FP_M_ACCH 01777 /* AC char mask incl Q,P */
/* Instruction format */
#define INST_T_DEC 0300000000000 /* if nz, takes decr */
#define INST_T_CXR1 0000000100000 /* if nz, update XR1 */
#define INST_V_OPD 33 /* decrement opcode */
#define INST_M_OPD 07
#define INST_V_DEC 18 /* decrement */
#define INST_M_DEC 077777
#define INST_V_OPC 24 /* normal opcode */
#define INST_M_OPC 0777
#define INST_V_IND 22 /* indirect */
#define INST_IND (3 << INST_V_IND)
#define INST_V_CCNT 18 /* convert count */
#define INST_M_CCNT 0377
#define INST_V_VCNT 18 /* vlm/vdh count */
#define INST_M_VCNT 077
#define INST_V_TAG 15 /* index */
#define INST_M_TAG 07
#define INST_V_ADDR 0
#define INST_M_ADDR 077777
#define GET_OPD(x) ((uint32) (((x) >> INST_V_OPD) & INST_M_OPD))
#define GET_DEC(x) ((uint32) (((x) >> INST_V_DEC) & INST_M_DEC))
#define GET_OPC(x) (((uint32) (((x) >> INST_V_OPC) & INST_M_OPC)) | \
(((x) & SIGN)? 01000: 0))
#define TST_IND(x) (((x) & INST_IND) == INST_IND)
#define GET_CCNT(x) ((uint32) (((x) >> INST_V_CCNT) & INST_M_CCNT))
#define GET_VCNT(x) ((uint32) (((x) >> INST_V_VCNT) & INST_M_VCNT))
#define GET_TAG(x) ((uint32) (((x) >> INST_V_TAG) & INST_M_TAG))
/* Instruction decode flags */
#define I_4X 0x01 /* 7040, 7044 */
#define I_9X 0x02 /* 7090, 7094, CTSS */
#define I_94 0x04 /* 7094, CTSS */
#define I_CT 0x08 /* CTSS */
#define I_MODEL 0x0F /* option mask */
#define I_X 0x10 /* indexed */
#define I_N 0x20 /* indirect */
#define I_R 0x40 /* read */
#define I_D 0x80 /* double read */
#define I_XN (I_X|I_N)
#define I_XNR (I_X|I_N|I_R)
#define I_XND (I_X|I_N|I_D)
/* Memory protection (CTSS) */
#define VA_V_OFF 0 /* offset in block */
#define VA_N_OFF 8 /* width of offset */
#define VA_M_OFF ((1u << VA_N_OFF) - 1)
#define VA_OFF (VA_M_OFF << VA_V_OFF)
#define VA_V_BLK (VA_N_OFF) /* block */
#define VA_N_BLK (ASIZE - VA_N_OFF) /* width of block */
#define VA_M_BLK ((1u << VA_N_BLK) - 1)
#define VA_BLK (VA_M_BLK << VA_V_BLK)
/* Unsigned operations */
#define NEG(x) (~(x) + 1)
#define BIT_TST(w,b) (((w) >> (b)) & 1)
/* Device information block */
typedef struct {
t_stat (*chsel)(uint32 ch, uint32 sel, uint32 u);
t_stat (*write)(uint32 ch, t_uint64 val, uint32 flags);
} DIB;
/* BCD digits */
#define BCD_MASK 017
#define BCD_ZERO 012
#define BCD_ONE 001
#define BCD_TWO 002
#define BCD_AT 014
/* Channels */
#define NUM_CHAN 8 /* # channels */
#define CH_A 0 /* channel A */
#define CH_B 1
#define CH_C 2
#define CH_D 3
#define CH_E 4
#define CH_F 5
#define CH_G 6
#define CH_H 7
#define REQ_CH(x) (1u << (x))
/* All channel commands */
#define CHI_IND 0000000400000 /* ch inst indirect */
/* Channel selects - all channels */
#define CHSL_RDS 0001 /* data selects */
#define CHSL_WRS 0002
#define CHSL_SNS 0003
#define CHSL_CTL 0004
#define CHSL_FMT 0005
#define CHSL_WEF 0010 /* non-data selects */
#define CHSL_WBT 0011 /* 704X only */
#define CHSL_BSR 0012
#define CHSL_BSF 0013
#define CHSL_REW 0014
#define CHSL_RUN 0015
#define CHSL_SDN 0016
#define CHSL_2ND 0020 /* second state */
#define CHSL_3RD 0040 /* etc */
#define CHSL_4TH 0060
#define CHSL_5TH 0100
#define CHSL_NDS 0010 /* non-data sel flag */
#define CHSL_NUM 16
/* Channel commands - 7607/7289 - S12'19 */
#define CH6I_NST 0000000200000 /* ch inst no store */
#define CH6_IOCD 000
#define CH6_TCH 002
#define CH6_IORP 004
#define CH6_IORT 006
#define CH6_IOCP 010
#define CH6_IOCT 012
#define CH6_IOSP 014
#define CH6_IOST 016
#define CH6_OPMASK 016 /* without nostore */
#define TCH_LIMIT 5 /* TCH autoresolve limit */
/* Channel data flags - 7607 */
#define CH6DF_EOR 1 /* end of record */
#define CH6DF_VLD 2 /* input valid */
/* Channel commands - 7909 - S123'19 */
#define CH9_WTR 000
#define CH9_XMT 001
#define CH9_TCH 004
#define CH9_LIPT 005
#define CH9_CTL 010
#define CH9_CTLR 011
#define CH9_CTLW 012
#define CH9_SNS 013
#define CH9_LAR 014
#define CH9_SAR 015
#define CH9_TWT 016
#define CH9_CPYP 020
#define CH9_CPYD 024
#define CH9_TCM 025
#define CH9_LIP 031
#define CH9_TDC 032
#define CH9_LCC 033
#define CH9_SMS 034
#define CH9_ICC 035
#define CH9_ICCA 037 /* ignores bit <3> */
#define CH9_OPMASK 037
/* Channel data flags - 7909 */
#define CH9DF_STOP 1 /* stop */
#define CH9DF_VLD 2 /* input valid */
/* Extended parts of the command come from the decrement, stored in ch_wc */
#define CH9D_V_MASK 0 /* condition mask */
#define CH9D_M_MASK 077
#define CH9D_V_COND 12 /* condition select */
#define CH9D_M_COND 07
#define CH9D_MASK(x) (((x) >> CH9D_V_MASK) & CH9D_M_MASK)
#define CH9D_COND(x) (((x) >> CH9D_V_COND) & CH9D_M_COND)
#define CH9D_NST 020000 /* no store */
#define CH9D_B11 000100
/* Or from the effective address, stored in ch_ca */
#define CH9A_V_LCC 0 /* counter */
#define CH9A_M_LCC 077
#define CH9A_V_SMS 0 /* system mask */
#define CH9A_M_SMS 0177
#define CH9A_LCC(x) (((x) >> CH9A_V_LCC) & CH9A_M_LCC)
#define CH9A_SMS(x) (((x) >> CH9A_V_SMS) & CH9A_M_SMS)
/* Channel states - common */
#define CHXS_IDLE 0 /* idle */
#define CHXS_DSX 1 /* executing */
/* Channel states - 7607/7289 */
#define CH6S_PNDS 2 /* polling NDS */
#define CH6S_PDS 3 /* polling DS */
#define CH6S_NDS 4 /* nds, executing */
#define CH6S_DSW 5 /* ds, chan wait */
/* Channel traps - 7909 has only CMD (== TWT) */
#define CHTR_V_CME 0 /* cmd/eof enable */
#define CHTR_V_CLK 17 /* clock */
#define CHTR_V_TRC 18 /* tape check */
#define CHTR_V_TWT (CHTR_V_CME)
#define CHTR_CLK_SAV 006 /* clock */
#define CHTR_CHA_SAV 012 /* start of chan block */
#define CHTR_F_CMD 1 /* CMD flag (in decr) */
#define CHTR_F_TRC 2 /* TRC flag (in decr) */
#define CHTR_F_EOF 4 /* EOF flag (in decr) */
/* Channel interrupts - 7909 only */
#define CHINT_CHA_SAV 042 /* start of chan block */
/* Channel interrupt conditions - 7909 only */
#define CHINT_ADPC 001 /* adapter check */
#define CHINT_ATN2 002 /* attention 2 - ni */
#define CHINT_ATN1 004 /* attention 1 */
#define CHINT_UEND 010 /* unusual end */
#define CHINT_SEQC 020 /* sequence check */
#define CHINT_IOC 040 /* IO check */
/* Channel SMS flags - 7909 only */
#define CHSMS_SEL2 0001 /* select 2nd - ni */
#define CHSMS_IATN2 0002 /* inhibit atn2 - ni */
#define CHSMS_IATN1 0004 /* inhibit atn1 */
#define CHSMS_IUEND 0010 /* inhibit uend */
#define CHSMS_BCD 0020 /* BCD conversion - ni */
#define CHSMS_RBCK 0040 /* read backwards - ni */
#define CHSMS_ENCI 0100 /* enable noncon - ni */
/* Channel flags (7607 in right half, 7909 in left half) */
#define CHF_CMD 00000000001 /* cmd done */
#define CHF_TWT (CHF_CMD)
#define CHF_TRC 00000000002 /* tape check */
#define CHF_EOF 00000000004 /* end of file */
#define CHF_BOT 00000000010 /* beginning of tape */
#define CHF_EOT 00000000020 /* end of tape */
#define CHF_LDW 00000000040 /* LCH waiting */
#define CHF_EOR 00000000100 /* end of record */
#define CHF_IRQ 00001000000 /* intr request */
#define CHF_INT 00002000000 /* intr in prog */
#define CHF_WRS 00004000000 /* write */
#define CHF_RDS 00010000000 /* read */
#define CHF_PWR 00020000000 /* prepare to write */
#define CHF_PRD 00040000000 /* prepare to read */
#define CHF_V_COND 24 /* cond register */
#define CHF_M_COND 077
#define CHF_ADPC (CHINT_ADPC << CHF_V_COND) /* adapter check */
#define CHF_ATN2 (CHINT_ATN2 << CHF_V_COND) /* attention 2 */
#define CHF_ATN1 (CHINT_ATN1 << CHF_V_COND) /* attention 1 */
#define CHF_UEND (CHINT_UEND << CHF_V_COND) /* unusual end */
#define CHF_SEQC (CHINT_SEQC << CHF_V_COND) /* sequence check */
#define CHF_IOC (CHINT_IOC << CHF_V_COND) /* IO check */
#define CHF_V_LCC 30 /* loop ctrl counter */
#define CHF_M_LCC 077
#define CHF_CLR_7909 07775000177 /* 7909 clear flags */
#define CHF_SDC_7909 07776000000 /* 7909 SDC flags */
/* Channel characteristics (in dev.flags) */
#define DEV_7909 (1u << (DEV_V_UF + 0))
#define DEV_7289 (1u << (DEV_V_UF + 1))
#define DEV_CDLP (1u << (DEV_V_UF + 2))
#define DEV_7750 (1u << (DEV_V_UF + 3))
#define DEV_7631 (1u << (DEV_V_UF + 4))
/* Unit addresses - 7607/7289 only */
#define U_V_CH 9 /* channel number */
#define U_M_CH 077
#define U_V_UNIT 0
#define U_M_UNIT 0777
#define GET_U_CH(x) (((((uint32) (x)) >> U_V_CH) & U_M_CH) - 1)
#define GET_U_UNIT(x) ((((uint32) (x)) >> U_V_UNIT) & U_M_UNIT)
#define U_MTBCD 0201 /* BCD tape */
#define U_MTBIN 0221 /* binary tape */
#define U_CDR 0321 /* card reader */
#define U_CDP 0341 /* card punch */
#define U_LPBCD 0361 /* BCD print */
#define U_LPBIN 0362 /* binary print */
#define U_DRM 0330 /* 7320A drum */
#define MT_NUMDR 10
/* CTSS Chronolog clock */
#define CHRONO_CH (CH_A) /* channel A */
#define CHRONO_UNIT (7) /* unit 7 */
/* Interval timer */
#define CLK_CTR 05 /* counter */
#define CLK_TPS 60 /* 60Hz */
#define TMR_CLK 0 /* use timer 0 */
#define TMR_COM 1 /* 7750 timer */
/* Function prototypes and macros */
#define ReadP(p) M[p]
#define WriteP(p,d) M[p] = d
void cpu_ent_hist (uint32 pc, uint32 ea, t_uint64 ir, t_uint64 opnd);
t_stat ch_show_chan (FILE *st, UNIT *uptr, int32 val, void *desc);
t_stat ch6_end_nds (uint32 ch);
uint32 ch6_set_flags (uint32 ch, uint32 unit, uint32 flags);
t_stat ch6_err_disc (uint32 ch, uint32 unit, uint32 flags);
t_stat ch6_req_rd (uint32 ch, uint32 unit, t_uint64 val, uint32 flags);
t_stat ch6_req_wr (uint32 ch, uint32 unit);
t_bool ch6_qconn (uint32 ch, uint32 unit);
t_stat ch9_req_rd (uint32 ch, t_uint64 val);
void ch9_set_atn (uint32 ch);
void ch9_set_ioc (uint32 ch);
void ch9_set_end (uint32 ch, uint32 ireq);
t_bool ch9_qconn (uint32 ch);
void ch_set_map (void);
t_bool ch_qidle (void);
#endif

286
I7094/i7094_drm.c Normal file
View file

@ -0,0 +1,286 @@
/* i7094_drm.c: 7289/7320A drum simulator
Copyright (c) 2005-2006, 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.
drm 7289/7320A "fast" drum
Very little is known about this device; the behavior simulated here is
what is used by CTSS.
- The drum channel/controller behaves like a hybrid of the 7607 and the 7909.
It responds to SCD (like the 7909), gets its address from the channel
program (like the 7909), but responds to IOCD/IOCP (like the 7607) and
sets channel flags (like the 7607).
- The drum channel supports at least 2 drums. The maximum is 8 or less.
Physical drums are numbered from 0.
- Each drum has a capacity of 192K 36b words. This is divided into 6
"logical" drum of 32KW each. Each "logical" drum has 16 2048W "sectors".
Logical drums are numbered from 1.
- The drum's behavior if a sector boundary is crossed in mid-transfer is
unknown. CTSS never does this.
- The drum's behavior with record operations is unknown. CTSS only uses
IOCD and IOCP.
- The drum's error indicators are unknown. CTSS regards bits <0:2,13> of
the returned SCD data as errors, as well as the normal 7607 trap flags.
- The drum's rotational speed is unknown.
Assumptions in this simulator:
- Transfers may not cross a sector boundary. An attempt to do so sets
the EOF flag and causes an immediate disconnect.
- The hardware never sets end of record.
For speed, the entire drum is buffered in memory.
*/
#include "i7094_defs.h"
#include <math.h>
#define DRM_NUMDR 8 /* drums/controller */
/* Drum geometry */
#define DRM_NUMWDS 2048 /* words/sector */
#define DRM_SCMASK (DRM_NUMWDS - 1) /* sector mask */
#define DRM_NUMSC 16 /* sectors/log drum */
#define DRM_NUMWDL (DRM_NUMWDS * DRM_NUMSC) /* words/log drum */
#define DRM_NUMLD 6 /* log drums/phys drum */
#define DRM_SIZE (DRM_NUMLD * DRM_NUMWDL) /* words/phys drum */
#define GET_POS(x) ((int) fmod (sim_gtime() / ((double) (x)), \
((double) DRM_NUMWDS)))
/* Drum address from channel */
#define DRM_V_PHY 30 /* physical drum sel */
#define DRM_M_PHY 07
#define DRM_V_LOG 18 /* logical drum sel */
#define DRM_M_LOG 07
#define DRM_V_WDA 0 /* word address */
#define DRM_M_WDA (DRM_NUMWDL - 1)
#define DRM_GETPHY(x) (((uint32) ((x) >> DRM_V_PHY)) & DRM_M_PHY)
#define DRM_GETLOG(x) ((((uint32) (x)) >> DRM_V_LOG) & DRM_M_LOG)
#define DRM_GETWDA(x) ((((uint32) (x)) >> DRM_V_WDA) & DRM_M_WDA)
#define DRM_GETDA(x) (((DRM_GETLOG(x) - 1) * DRM_NUMWDL) + DRM_GETWDA(x))
/* Drum controller states */
#define DRM_IDLE 0
#define DRM_1ST 1
#define DRM_DATA 2
#define DRM_EOS 3
uint32 drm_ch = CH_G; /* drum channel */
uint32 drm_da = 0; /* drum address */
uint32 drm_sta = 0; /* state */
uint32 drm_op = 0; /* operation */
t_uint64 drm_chob = 0; /* output buf */
uint32 drm_chob_v = 0; /* valid */
int32 drm_time = 10; /* inter-word time */
extern uint32 ind_ioc;
t_stat drm_svc (UNIT *uptr);
t_stat drm_reset (DEVICE *dptr);
t_stat drm_chsel (uint32 ch, uint32 sel, uint32 unit);
t_stat drm_chwr (uint32 ch, t_uint64 val, uint32 flags);
t_bool drm_da_incr (void);
/* DRM data structures
drm_dev DRM device descriptor
drm_unit DRM unit descriptor
drm_reg DRM register list
*/
DIB drm_dib = { &drm_chsel, &drm_chwr };
UNIT drm_unit[] = {
{ UDATA (&drm_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_BUFABLE+
UNIT_MUSTBUF+UNIT_DISABLE, DRM_SIZE) },
{ UDATA (&drm_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_BUFABLE+
UNIT_MUSTBUF+UNIT_DISABLE, DRM_SIZE) },
{ UDATA (&drm_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_BUFABLE+
UNIT_MUSTBUF+UNIT_DISABLE+UNIT_DIS, DRM_SIZE) },
{ UDATA (&drm_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_BUFABLE+
UNIT_MUSTBUF+UNIT_DISABLE+UNIT_DIS, DRM_SIZE) },
{ UDATA (&drm_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_BUFABLE+
UNIT_MUSTBUF+UNIT_DISABLE+UNIT_DIS, DRM_SIZE) },
{ UDATA (&drm_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_BUFABLE+
UNIT_MUSTBUF+UNIT_DISABLE+UNIT_DIS, DRM_SIZE) },
{ UDATA (&drm_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_BUFABLE+
UNIT_MUSTBUF+UNIT_DISABLE+UNIT_DIS, DRM_SIZE) },
{ UDATA (&drm_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_BUFABLE+
UNIT_MUSTBUF+UNIT_DISABLE+UNIT_DIS, DRM_SIZE) }
};
REG drm_reg[] = {
{ ORDATA (STATE, drm_sta, 2) },
{ ORDATA (DA, drm_da, 18) },
{ FLDATA (OP, drm_op, 0) },
{ ORDATA (CHOB, drm_chob, 36) },
{ FLDATA (CHOBV, drm_chob_v, 0) },
{ DRDATA (TIME, drm_time, 24), REG_NZ + PV_LEFT },
{ DRDATA (CHAN, drm_ch, 3), REG_HRO },
{ NULL }
};
MTAB drm_mtab[] = {
{ MTAB_XTD|MTAB_VDV, 0, "CHANNEL", NULL, NULL, &ch_show_chan },
{ 0 }
};
DEVICE drm_dev = {
"DRM", drm_unit, drm_reg, drm_mtab,
DRM_NUMDR, 8, 18, 1, 8, 36,
NULL, NULL, &drm_reset,
NULL, NULL, NULL,
&drm_dib, DEV_DIS
};
/* Channel select routine */
t_stat drm_chsel (uint32 ch, uint32 sel, uint32 unit)
{
drm_ch = ch; /* save channel */
if (sel & CHSL_NDS) return ch6_end_nds (ch); /* nds? nop */
switch (sel) { /* case on cmd */
case CHSL_RDS: /* read */
case CHSL_WRS: /* write */
if (drm_sta != DRM_IDLE) return ERR_STALL; /* busy? */
drm_sta = DRM_1ST; /* initial state */
if (sel == CHSL_WRS) drm_op = 1; /* set read/write */
else drm_op = 0; /* LCHx sends addr */
break; /* wait for addr */
default: /* other */
return STOP_ILLIOP;
}
return SCPE_OK;
}
/* Channel write routine */
t_stat drm_chwr (uint32 ch, t_uint64 val, uint32 flags)
{
uint32 u, l;
int32 cp, dp;
if (drm_sta == DRM_1ST) {
u = DRM_GETPHY (val); /* get unit */
l = DRM_GETLOG (val); /* get logical address */
if ((u >= DRM_NUMDR) || /* invalid unit? */
(drm_unit[u].flags & UNIT_DIS) || /* disabled unit? */
(l == 0) || (l > DRM_NUMLD)) { /* invalid log drum? */
ch6_err_disc (ch, U_DRM, CHF_TRC); /* disconnect */
drm_sta = DRM_IDLE;
return SCPE_OK;
}
drm_da = DRM_GETDA (val); /* get drum addr */
cp = GET_POS (drm_time); /* current pos in sec */
dp = (drm_da & DRM_SCMASK) - cp; /* delta to desired pos */
if (dp <= 0) dp = dp + DRM_NUMWDS; /* if neg, add rev */
sim_activate (&drm_unit[u], dp * drm_time); /* schedule */
if (drm_op) ch6_req_wr (ch, U_DRM); /* if write, get word */
drm_sta = DRM_DATA;
drm_chob = 0; /* clr, inval buffer */
drm_chob_v = 0;
}
else {
drm_chob = val & DMASK;
drm_chob_v = 1;
}
return SCPE_OK;
}
/* Unit service - this code assumes the entire drum is buffered */
t_stat drm_svc (UNIT *uptr)
{
t_uint64 *fbuf = (t_uint64 *) uptr->filebuf;
if ((uptr->flags & UNIT_BUF) == 0) { /* not buf? */
ch6_err_disc (drm_ch, U_DRM, CHF_TRC); /* set TRC, disc */
drm_sta = DRM_IDLE; /* drum is idle */
return SCPE_UNATT;
}
if (drm_da >= DRM_SIZE) { /* nx logical drum? */
ch6_err_disc (drm_ch, U_DRM, CHF_EOF); /* set EOF, disc */
drm_sta = DRM_IDLE; /* drum is idle */
return SCPE_OK;
}
switch (drm_sta) { /* case on state */
case DRM_DATA: /* data */
if (drm_op) { /* write? */
if (drm_chob_v) drm_chob_v = 0; /* valid? clear */
else if (ch6_qconn (drm_ch, U_DRM)) /* no, chan conn? */
ind_ioc = 1; /* io check */
fbuf[drm_da] = drm_chob; /* get data */
if (drm_da >= uptr->hwmark) uptr->hwmark = drm_da + 1;
if (!drm_da_incr ()) ch6_req_wr (drm_ch, U_DRM);
}
else{ /* read */
ch6_req_rd (drm_ch, U_DRM, fbuf[drm_da], 0); /* send word to channel */
drm_da_incr ();
}
sim_activate (uptr, drm_time); /* next word */
break;
case DRM_EOS: /* end sector */
if (ch6_qconn (drm_ch, U_DRM)) /* drum still conn? */
ch6_err_disc (drm_ch, U_DRM, CHF_EOF); /* set EOF, disc */
drm_sta = DRM_IDLE; /* drum is idle */
break;
} /* end case */
return SCPE_OK;
}
/* Increment drum address - return true, set new state if end of sector */
t_bool drm_da_incr (void)
{
drm_da = drm_da + 1;
if (drm_da & DRM_SCMASK) return FALSE;
drm_sta = DRM_EOS;
return TRUE;
}
/* Reset routine */
t_stat drm_reset (DEVICE *dptr)
{
uint32 i;
drm_da = 0;
drm_op = 0;
drm_sta = DRM_IDLE;
drm_chob = 0;
drm_chob_v = 0;
for (i = 0; i < dptr->numunits; i++) sim_cancel (dptr->units + i);
return SCPE_OK;
}

1172
I7094/i7094_dsk.c Normal file

File diff suppressed because it is too large Load diff

1789
I7094/i7094_io.c Normal file

File diff suppressed because it is too large Load diff

365
I7094/i7094_lp.c Normal file
View file

@ -0,0 +1,365 @@
/* i7094_lp.c: IBM 716 line printer simulator
Copyright (c) 2003-2006, 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.
lpt 716 line printer
Internally, the 7094 works only with column binary and is limited to
72 columns of data. Each row of the printed line is represented by
72b of data (two 36b words). A complete print line consists of 12 rows
(24 36b words).
The printer can also echo part of what it prints, namely, the digit rows
plus the 8+3 and 8+4 combinations. This was intended for verification of
check printing. Echoed data is interspersed with output data in the
following order:
output row 9 to row 1
echo row "8+4"
output row 0
echo row "8+3"
output row 11
echo row 9
output row 12
echo row 8 to row 1
*/
#include "i7094_defs.h"
#define UNIT_V_CONS (UNIT_V_UF + 0) /* print to console */
#define UNIT_CONS (1u << UNIT_V_CONS)
#define UNIT_V_BZ (UNIT_V_UF + 1)
#define UNIT_V_48 (UNIT_V_UF + 2)
#define UNIT_BZ (1 << UNIT_V_BZ)
#define UNIT_48 (1 << UNIT_V_48)
#define GET_PCHAIN(x) (((x) >> UNIT_V_BZ) & (UNIT_BZ|UNIT_48))
#define LPT_BINLNT 24 /* bin buffer length */
#define LPT_ECHLNT 22 /* echo buffer length */
#define LPT_CHRLNT 80 /* char buffer length */
#define LPS_INIT 0 /* init state */
#define LPS_DATA 1 /* print data state */
#define ECS_DATA 2 /* echo data state */
#define LPS_END 3 /* end state */
#define LPB_9ROW 0 /* bin buf: 9 row */
#define LPB_8ROW 2 /* 8 row */
#define LPB_4ROW 10 /* 4 row */
#define LPB_3ROW 12 /* 3 row */
#define LPB_1ROW 16 /* 1 row */
#define LPB_12ROW 22 /* 12 row */
#define ECB_84ROW 0 /* echo buf: 8-4 row */
#define ECB_83ROW 2 /* 8-3 row */
#define ECB_9ROW 4 /* 9 row */
#define ECHO_F 0100 /* echo map: flag */
#define ECHO_MASK 0037 /* mask */
#define CMD_BIN 1 /* cmd: bcd/bin */
#define CMD_ECHO 2 /* cmd: wrs/rds */
uint32 lpt_sta = 0; /* state */
uint32 lpt_bptr = 0; /* buffer ptr */
uint32 lpt_cmd = 0; /* modes */
uint32 lpt_tstart = 27500; /* timing */
uint32 lpt_tstop = 27500;
uint32 lpt_tleft = 150;
uint32 lpt_tright = 4000;
t_uint64 lpt_chob = 0;
uint32 lpt_chob_v = 0;
t_uint64 lpt_bbuf[LPT_BINLNT]; /* binary buffer */
t_uint64 lpt_ebuf[LPT_ECHLNT]; /* echo buffer */
/* Echo ordering map */
static const uint8 echo_map[LPT_BINLNT + LPT_ECHLNT] = {
0, 1, 2, 3, 4, 5, 6, 7, /* write 9 to 1 */
8, 9, 10, 11, 12, 13, 14, 15,
16, 17,
0+ECHO_F, 1+ECHO_F, /* echo 8+4 */
18, 19, /* write 0 */
2+ECHO_F, 3+ECHO_F, /* echo 8+3 */
20, 21, /* write 11 */
4+ECHO_F, 5+ECHO_F, /* echo 9 */
22, 23, /* write 12 */
6+ECHO_F, 7+ECHO_F, 8+ECHO_F, 9+ECHO_F, /* echo 8 to 1 */
10+ECHO_F, 11+ECHO_F, 12+ECHO_F, 13+ECHO_F,
14+ECHO_F, 15+ECHO_F, 16+ECHO_F, 17+ECHO_F,
18+ECHO_F, 19+ECHO_F, 20+ECHO_F, 21+ECHO_F
};
extern uint32 ind_ioc;
extern t_uint64 bit_masks[36];
extern uint32 col_masks[12];
extern char bcd_to_ascii_a[64];
extern char bcd_to_ascii_h[64];
extern char bcd_to_pca[64];
extern char bcd_to_pch[64];
char *pch_table[4] = {
bcd_to_ascii_h, bcd_to_ascii_a, bcd_to_pch, bcd_to_pca,
};
t_stat lpt_reset (DEVICE *dptr);
t_stat lpt_svc (UNIT *uptr);
t_stat lpt_chsel (uint32 ch, uint32 sel, uint32 unit);
t_stat lpt_chwr (uint32 ch, t_uint64 val, uint32 flags);
t_stat lpt_end_line (UNIT *uptr);
extern char colbin_to_bcd (uint32 colbin);
/* LPT data structures
lpt_dev LPT device descriptor
lpt_unit LPT unit descriptor
lpt_reg LPT register list
*/
DIB lpt_dib = { &lpt_chsel, &lpt_chwr };
UNIT lpt_unit = {
UDATA (&lpt_svc, UNIT_SEQ+UNIT_ATTABLE+UNIT_CONS, 0)
};
REG lpt_reg[] = {
{ ORDATA (STATE, lpt_sta, 2) },
{ ORDATA (CMD, lpt_cmd, 2) },
{ ORDATA (CHOB, lpt_chob, 36) },
{ FLDATA (CHOBV, lpt_chob_v, 0) },
{ DRDATA (BPTR, lpt_bptr, 6), PV_LEFT },
{ BRDATA (BUF, lpt_bbuf, 8, 36, LPT_BINLNT) },
{ BRDATA (EBUF, lpt_ebuf, 8, 36, LPT_ECHLNT) },
{ DRDATA (POS, lpt_unit.pos, T_ADDR_W), PV_LEFT },
{ DRDATA (TSTART, lpt_tstart, 24), PV_LEFT + REG_NZ },
{ DRDATA (TSTOP, lpt_tstop, 24), PV_LEFT + REG_NZ },
{ DRDATA (TLEFT, lpt_tleft, 24), PV_LEFT + REG_NZ },
{ DRDATA (TRIGHT, lpt_tright, 24), PV_LEFT + REG_NZ },
{ NULL }
};
MTAB lpt_mod[] = {
{ UNIT_CONS, UNIT_CONS, "default to console", "DEFAULT" },
{ UNIT_CONS, 0 , "no default device", "NODEFAULT" },
{ UNIT_48, UNIT_48, "48 character chain", "48" },
{ UNIT_48, 0, "64 character chain", "64" },
{ UNIT_BZ, UNIT_BZ, "business set", "BUSINESS" },
{ UNIT_BZ, 0, "Fortran set", "FORTRAN" },
{ 0 }
};
DEVICE lpt_dev = {
"LPT", &lpt_unit, lpt_reg, lpt_mod,
1, 10, 31, 1, 8, 7,
NULL, NULL, &lpt_reset,
NULL, NULL, NULL,
&lpt_dib, DEV_DISABLE
};
/* Channel select routine */
t_stat lpt_chsel (uint32 ch, uint32 sel, uint32 unit)
{
if (sel & CHSL_NDS) return ch6_end_nds (ch); /* nds? nop */
switch (sel) { /* case on cmd */
case CHSL_RDS: /* read */
case CHSL_WRS: /* write */
if (!(lpt_unit.flags & (UNIT_ATT|UNIT_CONS))) /* not attached? */
return SCPE_UNATT;
if (sim_is_active (&lpt_unit)) /* busy? */
return ERR_STALL;
lpt_cmd = ((unit & 02)? CMD_BIN: 0) | /* save modes */
((sel == CHSL_RDS)? CMD_ECHO: 0);
lpt_sta = LPS_INIT; /* initial state */
sim_activate (&lpt_unit, lpt_tstart); /* start reader */
break;
default: /* other */
return STOP_ILLIOP;
}
return SCPE_OK;
}
/* Channel write routine
- Normal mode is processed here
- Echo mode is processed in the service routine (like a read) */
t_stat lpt_chwr (uint32 ch, t_uint64 val, uint32 eorfl)
{
uint32 u = (lpt_cmd & CMD_BIN)? U_LPBIN: U_LPBCD; /* reconstruct unit */
lpt_chob = val & DMASK; /* store data */
lpt_chob_v = 1; /* set valid */
if (lpt_sta == ECS_DATA) return SCPE_OK;
if (lpt_sta == LPS_DATA) {
lpt_bbuf[lpt_bptr++] = lpt_chob; /* store data */
if (eorfl || /* end record, or */
((lpt_cmd & CMD_BIN)? /* last word in buffer? */
(lpt_bptr > (LPB_1ROW + 1)): /* (binary mode) */
(lpt_bptr > (LPB_12ROW + 1)))) { /* (normal mode) */
ch6_set_flags (CH_A, u, CHF_EOR); /* set eor */
return lpt_end_line (&lpt_unit);
}
return SCPE_OK;
}
return SCPE_IERR;
}
/* Unit timeout */
t_stat lpt_svc (UNIT *uptr)
{
uint32 u = (lpt_cmd & CMD_BIN)? U_LPBIN: U_LPBCD; /* reconstruct unit */
uint32 i, map;
switch (lpt_sta) { /* case on state */
case LPS_INIT: /* initial state */
for (i = 0; i < LPT_BINLNT; i++) /* clear data buffer */
lpt_bbuf[i] = 0;
for (i = 0; i < LPT_ECHLNT; i++) /* clear echo buffer */
lpt_ebuf[i] = 0;
if (lpt_cmd & CMD_BIN) lpt_bptr = LPB_1ROW; /* set buffer ptr */
else lpt_bptr = LPB_9ROW;
if (lpt_cmd & CMD_ECHO) lpt_sta = ECS_DATA; /* set data state */
else lpt_sta = LPS_DATA;
ch6_req_wr (CH_A, u); /* request channel */
lpt_chob = 0; /* clr, inval buffer */
lpt_chob_v = 0;
sim_activate (uptr, lpt_tleft); /* go again */
break;
case LPS_DATA: /* print data state */
if (!ch6_qconn (CH_A, u)) /* disconnect? */
return lpt_end_line (uptr); /* line is done */
if (lpt_chob_v) lpt_chob_v = 0; /* valid? clear */
else ind_ioc = 1; /* no, io check */
ch6_req_wr (CH_A, u); /* request chan again */
sim_activate (uptr, (lpt_bptr & 1)? lpt_tleft: lpt_tright);
break;
case ECS_DATA: /* echo data state */
map = echo_map[lpt_bptr++]; /* map column */
if (map == ECHO_F) { /* first echo? */
lpt_ebuf[ECB_84ROW] = lpt_bbuf[LPB_8ROW] & lpt_bbuf[LPB_4ROW];
lpt_ebuf[ECB_84ROW + 1] = lpt_bbuf[LPB_8ROW + 1] & lpt_bbuf[LPB_4ROW + 1];
lpt_ebuf[ECB_83ROW] = lpt_bbuf[LPB_8ROW] & lpt_bbuf[LPB_3ROW];
lpt_ebuf[ECB_83ROW + 1] = lpt_bbuf[LPB_8ROW + 1] & lpt_bbuf[LPB_3ROW + 1];
for (i = 0; i < 18; i++) /* copy rows 9.. 1 */
lpt_ebuf[ECB_9ROW + i] = lpt_bbuf[LPB_9ROW + i];
}
if (map & ECHO_F) { /* echo cycle */
ch6_req_rd (CH_A, u, lpt_ebuf[map & ECHO_MASK], 0);
if (lpt_bptr >= (LPT_BINLNT + LPT_ECHLNT))
return lpt_end_line (uptr); /* done? */
sim_activate (uptr, lpt_tleft); /* short timer */
}
else { /* print cycle */
if (lpt_chob_v) lpt_chob_v = 0; /* valid? clear */
else ind_ioc = 1; /* no, io check */
lpt_bbuf[map] = lpt_chob; /* store in buffer */
sim_activate (uptr, (lpt_bptr & 1)? lpt_tleft: lpt_tright);
}
if (!(echo_map[lpt_bptr] & ECHO_F)) /* print word next? */
ch6_req_wr (CH_A, u); /* req channel */
break;
case LPS_END: /* end state */
if (ch6_qconn (CH_A, u)) { /* lpt still conn? */
lpt_sta = LPS_INIT; /* initial state */
sim_activate (uptr, 1); /* next line */
}
break;
}
return SCPE_OK;
}
/* End line routine */
t_stat lpt_end_line (UNIT *uptr)
{
uint32 i, j, col, row, bufw, colbin;
char *pch, bcd, lpt_cbuf[LPT_CHRLNT + 1];
t_uint64 dat;
pch = pch_table[GET_PCHAIN (lpt_unit.flags)]; /* get print chain */
for (col = 0; col < (LPT_CHRLNT + 1); col++) /* clear ascii buf */
lpt_cbuf[col] = ' ';
for (col = 0; col < 72; col++) { /* proc 72 columns */
colbin = 0;
dat = bit_masks[35 - (col % 36)]; /* mask for column */
for (row = 0; row < 12; row++) { /* proc 12 rows */
bufw = (row * 2) + (col / 36); /* index to buffer */
if (lpt_bbuf[bufw] & dat) colbin |= col_masks[row];
}
bcd = colbin_to_bcd (colbin); /* column bin -> BCD */
lpt_cbuf[col] = pch[bcd]; /* -> ASCII */
}
for (i = LPT_CHRLNT; (i > 0) &&
(lpt_cbuf[i - 1] == ' '); --i) ; /* trim spaces */
lpt_cbuf[i++] = '\n'; /* append nl */
if (uptr->flags & UNIT_ATT) { /* file? */
fxwrite (lpt_cbuf, 1, i, uptr->fileref); /* write line */
if (ferror (uptr->fileref)) { /* error? */
perror ("LPT I/O error");
clearerr (uptr->fileref);
return SCPE_IOERR;
}
uptr->pos = ftell (uptr->fileref); /* update position */
}
else if (uptr->flags & UNIT_CONS) { /* print to console? */
for (j = 0; j < i; j++) sim_putchar (lpt_cbuf[j]);
sim_putchar ('\r');
}
else return SCPE_UNATT; /* otherwise error */
uptr->pos = uptr->pos + strlen (lpt_cbuf); /* count char */
lpt_sta = LPS_END; /* end line state */
sim_cancel (uptr); /* cancel current */
sim_activate (uptr, lpt_tstop); /* long timer */
return SCPE_OK;
}
/* Reset routine */
t_stat lpt_reset (DEVICE *dptr)
{
uint32 i;
for (i = 0; i < LPT_BINLNT; i++) lpt_bbuf[i] = 0; /* clear bin buf */
for (i = 0; i < LPT_ECHLNT; i++) lpt_ebuf[i] = 0; /* clear echo buf */
lpt_sta = 0; /* clear state */
lpt_cmd = 0; /* clear modes */
lpt_bptr = 0; /* clear buf ptr */
lpt_chob = 0;
lpt_chob_v = 0;
sim_cancel (&lpt_unit); /* stop printer */
return SCPE_OK;
}

826
I7094/i7094_mt.c Normal file
View file

@ -0,0 +1,826 @@
/* i7094_mt.c: IBM 7094 magnetic tape simulator
Copyright (c) 2003-2006, Robert M Supnik
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Except as contained in this notice, the name of Robert M Supnik shall not be
used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from Robert M Supnik.
mt magtape simulator
*/
#include "i7094_defs.h"
#include "sim_tape.h"
#define UST u3 /* unit state */
#define UCH u4 /* channel number */
#define MTUF_V_LDN (MTUF_V_UF + 0)
#define MTUF_LDN (1 << MTUF_V_LDN)
#define MT_MAXFR ((1 << 18) + 2)
#define QCHRONO(c,u) ((cpu_model & I_CT) && \
((c) == CHRONO_CH) && ((u) == CHRONO_UNIT))
uint8 *mtxb[NUM_CHAN] = { NULL }; /* xfer buffer */
uint32 mt_unit[NUM_CHAN]; /* unit */
uint32 mt_bptr[NUM_CHAN];
uint32 mt_blnt[NUM_CHAN];
t_uint64 mt_chob[NUM_CHAN];
uint32 mt_chob_v[NUM_CHAN];
uint32 mt_tshort = 2;
uint32 mt_twef = 25000; /* 50 msec */
uint32 mt_tstart = 29000; /* 58 msec */
uint32 mt_tstop = 10000; /* 20 msec */
uint32 mt_tword = 50; /* 125 usec */
static const uint8 odd_par[64] = {
1, 0, 0, 1, 0, 1, 1, 0,
0, 1, 1, 0, 1, 0, 0, 1,
0, 1, 1, 0, 1, 0, 0, 1,
1, 0, 0, 1, 0, 1, 1, 0,
0, 1, 1, 0, 1, 0, 0, 1,
1, 0, 0, 1, 0, 1, 1, 0,
1, 0, 0, 1, 0, 1, 1, 0,
0, 1, 1, 0, 1, 0, 0, 1
};
static const char *tape_stat[] = {
"OK", "TMK", "UNATT", "IOERR", "INVRECLNT",
"FMT", "BOT", "EOM", "RECERR", "WRPROT"
};
extern uint32 PC;
extern uint32 cpu_model;
extern uint32 ind_ioc;
extern FILE *sim_deb;
extern char *sel_name[];
t_stat mt_chsel (uint32 ch, uint32 sel, uint32 unit);
t_stat mt_chwr (uint32 ch, t_uint64 val, uint32 flags);
t_stat mt_rec_end (UNIT *uptr);
t_stat mt_svc (UNIT *uptr);
t_stat mt_reset (DEVICE *dptr);
t_stat mt_attach (UNIT *uptr, char *cptr);
t_stat mt_boot (int32 unitno, DEVICE *dptr);
t_stat mt_map_err (UNIT *uptr, t_stat st);
extern uint32 chrono_rd (uint8 *buf, uint32 bufsiz);
/* MT data structures
mt_dev MT device descriptor
mt_unit MT unit list
mt_reg MT register list
mt_mod MT modifier list
*/
DIB mt_dib = { &mt_chsel, &mt_chwr };
MTAB mt_mod[] = {
{ MTUF_WLK, 0, "write enabled", "WRITEENABLED", NULL },
{ MTUF_WLK, MTUF_WLK, "write locked", "LOCKED", NULL },
{ MTUF_LDN, 0, "high density", "HIGH", NULL },
{ MTUF_LDN, MTUF_LDN, "low density", "LOW", NULL },
{ MTAB_XTD|MTAB_VUN, 0, "FORMAT", "FORMAT",
&sim_tape_set_fmt, &sim_tape_show_fmt, NULL },
{ 0 }
};
UNIT mta_unit[] = {
{ UDATA (NULL, UNIT_DIS, 0) },
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) }
};
REG mta_reg[] = {
{ ORDATA (UNIT, mt_unit[0], 5) },
{ ORDATA (CHOB, mt_chob[0], 36) },
{ FLDATA (CHOBV, mt_chob_v[0], 0) },
{ DRDATA (BPTR, mt_bptr[0], 16), PV_LEFT },
{ DRDATA (BLNT, mt_blnt[0], 16), PV_LEFT },
{ BRDATA (BUF, NULL, 8, 7, MT_MAXFR) },
{ DRDATA (TWEF, mt_twef, 24), REG_NZ + PV_LEFT },
{ DRDATA (TSHORT, mt_tshort, 24), REG_NZ + PV_LEFT },
{ DRDATA (TSTART, mt_tstart, 24), REG_NZ + PV_LEFT },
{ DRDATA (TSTOP, mt_tstop, 24), REG_NZ + PV_LEFT },
{ DRDATA (TWORD, mt_tword, 24), REG_NZ + PV_LEFT },
{ URDATA (UST, mta_unit[0].UST, 8, 5, 0, MT_NUMDR + 1, 0) },
{ URDATA (POS, mta_unit[0].pos, 10, T_ADDR_W, 0,
MT_NUMDR + 1, PV_LEFT | REG_RO) },
{ NULL }
};
UNIT mtb_unit[] = {
{ UDATA (NULL, UNIT_DIS, 0) },
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) }
};
REG mtb_reg[] = {
{ ORDATA (UNIT, mt_unit[1], 5) },
{ ORDATA (CHOB, mt_chob[1], 36) },
{ FLDATA (CHOBV, mt_chob_v[1], 0) },
{ DRDATA (BPTR, mt_bptr[1], 16), PV_LEFT },
{ DRDATA (BLNT, mt_blnt[1], 16), PV_LEFT },
{ BRDATA (BUF, NULL, 8, 7, MT_MAXFR) },
{ DRDATA (TWEF, mt_twef, 24), REG_NZ + PV_LEFT },
{ DRDATA (TSHORT, mt_tshort, 24), REG_NZ + PV_LEFT },
{ DRDATA (TSTART, mt_tstart, 24), REG_NZ + PV_LEFT },
{ DRDATA (TSTOP, mt_tstop, 24), REG_NZ + PV_LEFT },
{ DRDATA (TWORD, mt_tword, 24), REG_NZ + PV_LEFT },
{ URDATA (UST, mtb_unit[0].UST, 8, 5, 0, MT_NUMDR + 1, 0) },
{ URDATA (POS, mtb_unit[0].pos, 10, T_ADDR_W, 0,
MT_NUMDR + 1, PV_LEFT | REG_RO) },
{ NULL }
};
UNIT mtc_unit[] = {
{ UDATA (NULL, UNIT_DIS, 0) },
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) }
};
REG mtc_reg[] = {
{ ORDATA (UNIT, mt_unit[2], 5) },
{ ORDATA (CHOB, mt_chob[2], 36) },
{ FLDATA (CHOBV, mt_chob_v[2], 0) },
{ DRDATA (BPTR, mt_bptr[2], 16), PV_LEFT },
{ DRDATA (BLNT, mt_blnt[2], 16), PV_LEFT },
{ BRDATA (BUF, NULL, 8, 7, MT_MAXFR) },
{ DRDATA (TWEF, mt_twef, 24), REG_NZ + PV_LEFT },
{ DRDATA (TSHORT, mt_tshort, 24), REG_NZ + PV_LEFT },
{ DRDATA (TSTART, mt_tstart, 24), REG_NZ + PV_LEFT },
{ DRDATA (TSTOP, mt_tstop, 24), REG_NZ + PV_LEFT },
{ DRDATA (TWORD, mt_tword, 24), REG_NZ + PV_LEFT },
{ URDATA (UST, mtc_unit[0].UST, 8, 5, 0, MT_NUMDR + 1, 0) },
{ URDATA (POS, mtc_unit[0].pos, 10, T_ADDR_W, 0,
MT_NUMDR + 1, PV_LEFT | REG_RO) },
{ NULL }
};
UNIT mtd_unit[] = {
{ UDATA (NULL, UNIT_DIS, 0) },
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) }
};
REG mtd_reg[] = {
{ ORDATA (UNIT, mt_unit[3], 5) },
{ ORDATA (CHOB, mt_chob[3], 36) },
{ FLDATA (CHOBV, mt_chob_v[3], 0) },
{ DRDATA (BPTR, mt_bptr[3], 16), PV_LEFT },
{ DRDATA (BLNT, mt_blnt[3], 16), PV_LEFT },
{ BRDATA (BUF, NULL, 8, 7, MT_MAXFR) },
{ DRDATA (TWEF, mt_twef, 24), REG_NZ + PV_LEFT },
{ DRDATA (TSHORT, mt_tshort, 24), REG_NZ + PV_LEFT },
{ DRDATA (TSTART, mt_tstart, 24), REG_NZ + PV_LEFT },
{ DRDATA (TSTOP, mt_tstop, 24), REG_NZ + PV_LEFT },
{ DRDATA (TWORD, mt_tword, 24), REG_NZ + PV_LEFT },
{ URDATA (UST, mtd_unit[0].UST, 8, 5, 0, MT_NUMDR + 1, 0) },
{ URDATA (POS, mtd_unit[0].pos, 10, T_ADDR_W, 0,
MT_NUMDR + 1, PV_LEFT | REG_RO) },
{ NULL }
};
UNIT mte_unit[] = {
{ UDATA (NULL, UNIT_DIS, 0) },
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) }
};
REG mte_reg[] = {
{ ORDATA (UNIT, mt_unit[4], 5) },
{ ORDATA (CHOB, mt_chob[4], 36) },
{ FLDATA (CHOBV, mt_chob_v[4], 0) },
{ DRDATA (BPTR, mt_bptr[4], 16), PV_LEFT },
{ DRDATA (BLNT, mt_blnt[4], 16), PV_LEFT },
{ BRDATA (BUF, NULL, 8, 7, MT_MAXFR) },
{ DRDATA (TWEF, mt_twef, 24), REG_NZ + PV_LEFT },
{ DRDATA (TSHORT, mt_tshort, 24), REG_NZ + PV_LEFT },
{ DRDATA (TSTART, mt_tstart, 24), REG_NZ + PV_LEFT },
{ DRDATA (TSTOP, mt_tstop, 24), REG_NZ + PV_LEFT },
{ DRDATA (TWORD, mt_tword, 24), REG_NZ + PV_LEFT },
{ URDATA (UST, mte_unit[0].UST, 8, 5, 0, MT_NUMDR + 1, 0) },
{ URDATA (POS, mte_unit[0].pos, 10, T_ADDR_W, 0,
MT_NUMDR + 1, PV_LEFT | REG_RO) },
{ NULL }
};
UNIT mtf_unit[] = {
{ UDATA (NULL, UNIT_DIS, 0) },
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) }
};
REG mtf_reg[] = {
{ ORDATA (UNIT, mt_unit[5], 5) },
{ ORDATA (CHOB, mt_chob[5], 36) },
{ FLDATA (CHOBV, mt_chob_v[5], 0) },
{ DRDATA (BPTR, mt_bptr[5], 16), PV_LEFT },
{ DRDATA (BLNT, mt_blnt[5], 16), PV_LEFT },
{ BRDATA (BUF, NULL, 8, 7, MT_MAXFR) },
{ DRDATA (TWEF, mt_twef, 24), REG_NZ + PV_LEFT },
{ DRDATA (TSHORT, mt_tshort, 24), REG_NZ + PV_LEFT },
{ DRDATA (TSTART, mt_tstart, 24), REG_NZ + PV_LEFT },
{ DRDATA (TSTOP, mt_tstop, 24), REG_NZ + PV_LEFT },
{ DRDATA (TWORD, mt_tword, 24), REG_NZ + PV_LEFT },
{ URDATA (UST, mtf_unit[0].UST, 8, 5, 0, MT_NUMDR + 1, 0) },
{ URDATA (POS, mtf_unit[0].pos, 10, T_ADDR_W, 0,
MT_NUMDR + 1, PV_LEFT | REG_RO) },
{ NULL }
};
UNIT mtg_unit[] = {
{ UDATA (NULL, UNIT_DIS, 0) },
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) }
};
REG mtg_reg[] = {
{ ORDATA (UNIT, mt_unit[6], 5) },
{ ORDATA (CHOB, mt_chob[6], 36) },
{ FLDATA (CHOBV, mt_chob_v[6], 0) },
{ DRDATA (BPTR, mt_bptr[6], 16), PV_LEFT },
{ DRDATA (BLNT, mt_blnt[6], 16), PV_LEFT },
{ BRDATA (BUF, NULL, 8, 7, MT_MAXFR) },
{ DRDATA (TWEF, mt_twef, 24), REG_NZ + PV_LEFT },
{ DRDATA (TSHORT, mt_tshort, 24), REG_NZ + PV_LEFT },
{ DRDATA (TSTART, mt_tstart, 24), REG_NZ + PV_LEFT },
{ DRDATA (TSTOP, mt_tstop, 24), REG_NZ + PV_LEFT },
{ DRDATA (TWORD, mt_tword, 24), REG_NZ + PV_LEFT },
{ URDATA (UST, mtg_unit[0].UST, 8, 5, 0, MT_NUMDR + 1, 0) },
{ URDATA (POS, mtg_unit[0].pos, 10, T_ADDR_W, 0,
MT_NUMDR + 1, PV_LEFT | REG_RO) },
{ NULL }
};
UNIT mth_unit[] = {
{ UDATA (NULL, UNIT_DIS, 0) },
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) }
};
REG mth_reg[] = {
{ ORDATA (UNIT, mt_unit[7], 5) },
{ ORDATA (CHOB, mt_chob[7], 36) },
{ FLDATA (CHOBV, mt_chob_v[7], 0) },
{ DRDATA (BPTR, mt_bptr[7], 16), PV_LEFT },
{ DRDATA (BLNT, mt_blnt[7], 16), PV_LEFT },
{ BRDATA (BUF, NULL, 8, 7, MT_MAXFR) },
{ DRDATA (TWEF, mt_twef, 24), REG_NZ + PV_LEFT },
{ DRDATA (TSHORT, mt_tshort, 24), REG_NZ + PV_LEFT },
{ DRDATA (TSTART, mt_tstart, 24), REG_NZ + PV_LEFT },
{ DRDATA (TSTOP, mt_tstop, 24), REG_NZ + PV_LEFT },
{ DRDATA (TWORD, mt_tword, 24), REG_NZ + PV_LEFT },
{ URDATA (UST, mth_unit[0].UST, 8, 5, 0, MT_NUMDR + 1, 0) },
{ URDATA (POS, mth_unit[0].pos, 10, T_ADDR_W, 0,
MT_NUMDR + 1, PV_LEFT | REG_RO) },
{ NULL }
};
DEVICE mt_dev[NUM_CHAN] = {
{
"MTA", mta_unit, mta_reg, mt_mod,
MT_NUMDR + 1, 10, 31, 1, 8, 8,
NULL, NULL, &mt_reset,
&mt_boot, &mt_attach, &sim_tape_detach,
&mt_dib, DEV_DEBUG
},
{
"MTB", mtb_unit, mtb_reg, mt_mod,
MT_NUMDR + 1, 10, 31, 1, 8, 8,
NULL, NULL, &mt_reset,
NULL, &mt_attach, &sim_tape_detach,
&mt_dib, DEV_DIS|DEV_DEBUG
},
{
"MTC", mtc_unit, mtc_reg, mt_mod,
MT_NUMDR + 1, 10, 31, 1, 8, 8,
NULL, NULL, &mt_reset,
NULL, &mt_attach, &sim_tape_detach,
&mt_dib, DEV_DIS|DEV_DEBUG
},
{
"MTD", mtd_unit, mtd_reg, mt_mod,
MT_NUMDR + 1, 10, 31, 1, 8, 8,
NULL, NULL, &mt_reset,
NULL, &mt_attach, &sim_tape_detach,
&mt_dib, DEV_DIS|DEV_DEBUG
},
{
"MTE", mte_unit, mte_reg, mt_mod,
MT_NUMDR + 1, 10, 31, 1, 8, 8,
NULL, NULL, &mt_reset,
NULL, &mt_attach, &sim_tape_detach,
&mt_dib, DEV_DIS|DEV_DEBUG
},
{
"MTF", mtf_unit, mtf_reg, mt_mod,
MT_NUMDR + 1, 10, 31, 1, 8, 8,
NULL, NULL, &mt_reset,
NULL, &mt_attach, &sim_tape_detach,
&mt_dib, DEV_DIS|DEV_DEBUG
},
{
"MTG", mtg_unit, mtg_reg, mt_mod,
MT_NUMDR + 1, 10, 31, 1, 8, 8,
NULL, NULL, &mt_reset,
NULL, &mt_attach, &sim_tape_detach,
&mt_dib, DEV_DIS|DEV_DEBUG
},
{
"MTH", mth_unit, mth_reg, mt_mod,
MT_NUMDR + 1, 10, 31, 1, 8, 8,
NULL, NULL, &mt_reset,
NULL, &mt_attach, &sim_tape_detach,
&mt_dib, DEV_DIS|DEV_DEBUG
}
};
/* Select controller
Inputs:
ch = channel
cmd = select command
unit = unit
Outputs:
status = SCPE_OK if ok
STOP_STALL if busy
error code if error
*/
static const int mt_must_att[CHSL_NUM] = {
0, 1, 1, 0, 1, 1, 0, 0,
1, 1, 1, 1, 1, 1, 0, 0
};
static const int mt_will_wrt[CHSL_NUM] = {
0, 0, 1, 0, 0, 1, 0, 0,
1, 1, 0, 0, 0, 0, 0, 0
};
t_stat mt_chsel (uint32 ch, uint32 cmd, uint32 unit)
{
UNIT *uptr;
uint32 u = unit & 017;
if ((ch >= NUM_CHAN) || (cmd == 0) || (cmd >= CHSL_NUM))
return SCPE_IERR; /* invalid arg? */
if (mt_dev[ch].flags & DEV_DIS) return STOP_NXDEV; /* disabled? */
if ((u == 0) || (u > MT_NUMDR)) return STOP_NXDEV; /* valid unit? */
uptr = mt_dev[ch].units + u; /* get unit ptr */
if (uptr->flags & UNIT_DIS) return STOP_NXDEV; /* disabled? */
if (mt_unit[ch] || sim_is_active (uptr)) /* ctrl or unit busy? */
return ERR_STALL; /* stall */
if (QCHRONO (ch, u)) { /* Chronolog clock? */
if (cmd != CHSL_RDS) return STOP_ILLIOP; /* only reads */
sim_activate (uptr, mt_tword); /* responds quickly */
}
else { /* real tape */
if (!(uptr->flags & UNIT_ATT) && mt_must_att[cmd]) /* unit unatt? */
return SCPE_UNATT;
if (sim_tape_wrp (uptr) && mt_will_wrt[cmd]) /* unit wrp && write? */
return STOP_WRP;
if (DEBUG_PRS (mt_dev[ch])) fprintf (sim_deb,
">>%s%d %s, pos = %d\n", mt_dev[ch].name, u, sel_name[cmd], uptr->pos);
switch (cmd) { /* case on cmd */
case CHSL_RDS:
case CHSL_WRS:
case CHSL_BSR:
case CHSL_BSF: /* rd, wr, backspace */
sim_activate (uptr, mt_tstart); /* schedule op */
break;
case CHSL_WEF: /* write eof? */
sim_activate (uptr, mt_twef); /* schedule op */
break;
case CHSL_RUN:
sim_activate (uptr, mt_tshort); /* schedule quick event */
break;
case CHSL_REW:
case CHSL_SDN: /* rew, rew/unl, set det */
sim_activate (uptr, mt_tshort); /* schedule quick event */
break;
default:
return SCPE_IERR;
} /* end switch */
} /* end else */
uptr->UST = cmd; /* set cmd */
mt_unit[ch] = unit & 0777; /* save unit */
return SCPE_OK;
}
/* Channel write routine */
t_stat mt_chwr (uint32 ch, t_uint64 val, uint32 eorfl)
{
int32 k, u;
uint8 by, *xb;
UNIT *uptr;
if (ch >= NUM_CHAN) return SCPE_IERR; /* invalid chan? */
xb = mtxb[ch]; /* get xfer buf */
u = mt_unit[ch] & 017;
if ((xb == NULL) || (u > MT_NUMDR)) return SCPE_IERR; /* invalid args? */
uptr = mt_dev[ch].units + u; /* get unit */
mt_chob[ch] = val & DMASK; /* save word from chan */
mt_chob_v[ch] = 1; /* set valid */
if (uptr->UST == (CHSL_WRS|CHSL_2ND)) { /* data write? */
for (k = 30; /* proc 6 bytes */
(k >= 0) && (mt_bptr[ch] < MT_MAXFR);
k = k - 6) {
by = (uint8) ((val >> k) & 077); /* get byte */
if ((mt_unit[ch] & 020) == 0) { /* BCD? */
if (by == 0) by = BCD_ZERO; /* cvt bin 0 */
else if (by & 020) by = by ^ 040; /* invert zones */
if (!odd_par[by]) by = by | 0100; /* even parity */
}
else if (odd_par[by]) by = by | 0100; /* bin, odd par */
xb[mt_bptr[ch]++] = by; /* put in buffer */
}
if (eorfl) return mt_rec_end (uptr); /* EOR? write rec */
return SCPE_OK;
}
return SCPE_IERR;
}
/* Unit timeout */
t_stat mt_svc (UNIT *uptr)
{
uint32 i, u, ch = uptr->UCH; /* get channel number */
uint8 by, *xb = mtxb[ch]; /* get xfer buffer */
t_uint64 dat;
t_mtrlnt bc;
t_stat r;
if (xb == NULL) return SCPE_IERR; /* valid buffer? */
u = uptr - mt_dev[ch].units;
switch (uptr->UST) { /* case on state */
case CHSL_RDS: /* read start */
if (QCHRONO (ch, mt_unit[ch] & 017)) /* Chronolog clock? */
bc = chrono_rd (xb, MT_MAXFR); /* read clock */
else { /* real tape */
r = sim_tape_rdrecf (uptr, xb, &bc, MT_MAXFR); /* read record */
if (r = mt_map_err (uptr, r)) return r; /* map status */
if (mt_unit[ch] == 0) return SCPE_OK; /* disconnected? */
} /* end else Chrono */
if (!ch6_qconn (ch, mt_unit[ch])) { /* chan disconnected? */
mt_unit[ch] = 0; /* clr ctrl busy */
return SCPE_OK;
}
for (i = bc; i < (bc + 6); i++) xb[i] = 0; /* extra 0's */
mt_bptr[ch] = 0; /* set ptr, lnt */
mt_blnt[ch] = bc;
uptr->UST = CHSL_RDS|CHSL_2ND; /* next state */
sim_activate (uptr, mt_tword);
break;
case CHSL_RDS|CHSL_2ND: /* read word */
for (i = 0, dat = 0; i < 6; i++) { /* proc 6 bytes */
by = xb[mt_bptr[ch]++] & 077; /* get next byte */
if ((mt_unit[ch] & 020) == 0) { /* BCD? */
if (by == BCD_ZERO) by = 0; /* cvt BCD 0 */
else if (by & 020) by = by ^ 040; /* invert zones */
}
dat = (dat << 6) | ((t_uint64) by);
}
if (mt_bptr[ch] >= mt_blnt[ch]) { /* end of record? */
ch6_req_rd (ch, mt_unit[ch], dat, CH6DF_EOR);
uptr->UST = CHSL_RDS|CHSL_3RD; /* next state */
sim_activate (uptr, mt_tstop); /* long timing */
}
else {
ch6_req_rd (ch, mt_unit[ch], dat, 0); /* send to channel */
sim_activate (uptr, mt_tword); /* next word */
}
break;
case CHSL_RDS|CHSL_3RD: /* end record */
if (ch6_qconn (ch, mt_unit[ch])) { /* ch still conn? */
uptr->UST = CHSL_RDS; /* initial state */
sim_activate (uptr, mt_tshort); /* sched next record */
}
else mt_unit[ch] = 0; /* clr ctrl busy */
if (DEBUG_PRS (mt_dev[ch])) fprintf (sim_deb,
">>%s%d RDS complete, pos = %d, %s\n",
mt_dev[ch].name, u, uptr->pos, mt_unit[ch]? "continuing": "disconnecting");
return SCPE_OK;
case CHSL_WRS: /* write start */
if (!ch6_qconn (ch, mt_unit[ch])) { /* chan disconnected? */
mt_unit[ch] = 0; /* clr ctrl busy */
return SCPE_OK; /* (writes blank tape) */
}
mt_bptr[ch] = 0; /* init buffer */
uptr->UST = CHSL_WRS|CHSL_2ND; /* next state */
ch6_req_wr (ch, mt_unit[ch]); /* request channel */
mt_chob[ch] = 0; /* clr, inval buffer */
mt_chob_v[ch] = 0;
sim_activate (uptr, mt_tword); /* wait for word */
break;
case CHSL_WRS|CHSL_2ND: /* write word */
if (!ch6_qconn (ch, mt_unit[ch])) /* disconnected? */
return mt_rec_end (uptr); /* write record */
if (mt_chob_v[ch]) mt_chob_v[ch] = 0; /* valid? clear */
else ind_ioc = 1; /* no, io check */
ch6_req_wr (ch, mt_unit[ch]); /* request channel */
sim_activate (uptr, mt_tword); /* next word */
break;
case CHSL_WRS|CHSL_3RD: /* write stop */
if (ch6_qconn (ch, mt_unit[ch])) { /* chan active? */
uptr->UST = CHSL_WRS; /* initial state */
sim_activate (uptr, mt_tshort); /* sched next record */
}
else mt_unit[ch] = 0; /* clr ctrl busy */
if (DEBUG_PRS (mt_dev[ch])) fprintf (sim_deb,
">>%s%d WRS complete, pos = %d, %s\n",
mt_dev[ch].name, u, uptr->pos, mt_unit[ch]? "continuing": "disconnecting");
return SCPE_OK;
case CHSL_BSR: /* backspace rec */
r = sim_tape_sprecr (uptr, &bc); /* space backwards */
mt_unit[ch] = 0; /* clr ctrl busy */
ch6_end_nds (ch); /* disconnect */
if (DEBUG_PRS (mt_dev[ch])) fprintf (sim_deb,
">>%s%d BSR complete, pos = %d\n", mt_dev[ch].name, u, uptr->pos);
if (r == MTSE_TMK) return SCPE_OK; /* allow tape mark */
return mt_map_err (uptr, r);
case CHSL_BSF: /* backspace file */
while ((r = sim_tape_sprecr (uptr, &bc)) == MTSE_OK) ;
mt_unit[ch] = 0; /* clr ctrl busy */
ch6_end_nds (ch); /* disconnect */
if (DEBUG_PRS (mt_dev[ch])) fprintf (sim_deb,
">>%s%d BSF complete, pos = %d\n", mt_dev[ch].name, u, uptr->pos);
if (r == MTSE_TMK) return SCPE_OK; /* allow tape mark */
return mt_map_err (uptr, r); /* map others */
case CHSL_WEF: /* write eof */
r = sim_tape_wrtmk (uptr); /* write tape mark */
mt_unit[ch] = 0; /* clr ctrl busy */
ch6_end_nds (ch); /* disconnect */
if (DEBUG_PRS (mt_dev[ch])) fprintf (sim_deb,
">>%s%d WEF complete, pos = %d\n", mt_dev[ch].name, u, uptr->pos);
return mt_map_err (uptr, r);
case CHSL_REW: case CHSL_RUN: /* rewind, unload */
uptr->UST = uptr->UST | CHSL_2ND; /* set 2nd state */
sim_activate (uptr, mt_tstart); /* reactivate */
mt_unit[ch] = 0; /* clr ctrl busy */
ch6_end_nds (ch); /* disconnect */
return SCPE_OK;
case CHSL_REW | CHSL_2ND:
sim_tape_rewind (uptr);
if (DEBUG_PRS (mt_dev[ch])) fprintf (sim_deb,
">>%s%d REW complete, pos = %d\n", mt_dev[ch].name, u, uptr->pos);
return SCPE_OK;
case CHSL_RUN | CHSL_2ND:
sim_tape_detach (uptr);
if (DEBUG_PRS (mt_dev[ch])) fprintf (sim_deb,
">>%s%d RUN complete, pos = %d\n", mt_dev[ch].name, u, uptr->pos);
return SCPE_OK;
case CHSL_SDN:
if (mt_unit[ch] & 020) /* set density flag */
uptr->flags = uptr-> flags & ~MTUF_LDN;
else uptr->flags = uptr->flags | MTUF_LDN;
mt_unit[ch] = 0; /* clr ctrl busy */
ch6_end_nds (ch); /* disconnect */
if (DEBUG_PRS (mt_dev[ch])) fprintf (sim_deb,
">>%s%d SDN complete, pos = %d\n", mt_dev[ch].name, u, uptr->pos);
return SCPE_OK;
default:
return SCPE_IERR;
}
return SCPE_OK;
}
/* End record routine */
t_stat mt_rec_end (UNIT *uptr)
{
uint32 ch = uptr->UCH;
uint8 *xb = mtxb[ch];
t_stat r;
if (mt_bptr[ch]) { /* any data? */
if (xb == NULL) return SCPE_IERR;
r = sim_tape_wrrecf (uptr, xb, mt_bptr[ch]); /* write record */
if (r = mt_map_err (uptr, r)) return r; /* map error */
}
uptr->UST = CHSL_WRS|CHSL_3RD; /* next state */
sim_cancel (uptr); /* cancel current */
sim_activate (uptr, mt_tstop); /* long timing */
return SCPE_OK;
}
/* Map tape error status */
t_stat mt_map_err (UNIT *uptr, t_stat st)
{
uint32 ch = uptr->UCH;
uint32 u = mt_unit[ch];
uint32 up = uptr - mt_dev[ch].units;
if ((st != MTSE_OK) && DEBUG_PRS (mt_dev[ch])) fprintf (sim_deb,
">>%s%d status = %s, pos = %d\n", mt_dev[ch].name, up, tape_stat[st], uptr->pos);
switch (st) {
case MTSE_FMT: /* illegal fmt */
case MTSE_UNATT: /* not attached */
ch6_err_disc (ch, u, CHF_TRC);
mt_unit[ch] = 0; /* disconnect */
return SCPE_IERR;
case MTSE_IOERR: /* IO error */
ch6_err_disc (ch, u, CHF_TRC);
mt_unit[ch] = 0; /* disconnect */
return SCPE_IOERR;
case MTSE_INVRL: /* invalid rec lnt */
ch6_err_disc (ch, u, CHF_TRC);
mt_unit[ch] = 0; /* disconnect */
return SCPE_MTRLNT;
case MTSE_WRP: /* write protect */
ch6_err_disc (ch, u, 0);
mt_unit[ch] = 0; /* disconnect */
return STOP_WRP;
case MTSE_EOM: /* end of medium */
case MTSE_TMK: /* tape mark */
ch6_err_disc (ch, u, CHF_EOF);
mt_unit[ch] = 0; /* disconnect */
break;
case MTSE_RECE: /* record in error */
ch6_set_flags (ch, u, CHF_TRC);
break;
case MTSE_BOT: /* reverse into BOT */
ch6_set_flags (ch, u, CHF_BOT);
break;
case MTSE_OK: /* no error */
break;
}
return SCPE_OK;
}
/* Magtape reset */
t_stat mt_reset (DEVICE *dptr)
{
uint32 ch = dptr - &mt_dev[0];
uint32 j;
REG *rptr;
UNIT *uptr;
if (mtxb[ch] == NULL) mtxb[ch] = (uint8 *) calloc (MT_MAXFR + 6, sizeof (uint8));
if (mtxb[ch] == NULL) return SCPE_MEM; /* allocate buffer */
rptr = find_reg ("BUF", NULL, dptr); /* update reg ptr */
if (rptr == NULL) return SCPE_IERR;
rptr->loc = (void *) mtxb[ch];
mt_unit[ch] = 0; /* clear busy */
mt_bptr[ch] = 0; /* clear buf ptrs */
mt_blnt[ch] = 0;
mt_chob[ch] = 0;
mt_chob_v[ch] = 0;
for (j = 1; j <= MT_NUMDR; j++) { /* for all units */
uptr = dptr->units + j;
uptr->UST = 0; /* clear state */
uptr->UCH = ch;
sim_cancel (uptr); /* stop activity */
} /* end for */
return SCPE_OK; /* done */
}
/* Magtape attach */
t_stat mt_attach (UNIT *uptr, char *cptr)
{
uptr->flags = uptr->flags & ~MTUF_LDN; /* start as hi den */
return sim_tape_attach (uptr, cptr);
}
/* Magtape boot */
#define BOOT_START 01000
static const t_uint64 boot_rom[5] = {
0076200000000 + U_MTBIN - 1, /* RDS MT_binary */
0054000000000 + BOOT_START + 4, /* RCHA *+3 */
0054400000000, /* LCHA 0 */
0002100000001, /* TTR 1 */
0500003000000, /* IOCT 0,,3 */
};
t_stat mt_boot (int32 unitno, DEVICE *dptr)
{
uint32 i, chan;
extern t_uint64 *M;
chan = dptr - &mt_dev[0] + 1;
WriteP (BOOT_START, boot_rom[0] + unitno + (chan << 9));
for (i = 1; i < 5; i++)
WriteP (BOOT_START + i, boot_rom[i]);
PC = BOOT_START;
return SCPE_OK;
}

718
I7094/i7094_sys.c Normal file
View file

@ -0,0 +1,718 @@
/* i7094_sys.c: IBM 7094 simulator interface
Copyright (c) 2003-2006, 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.
*/
#include "i7094_defs.h"
#include <ctype.h>
#include "i7094_dat.h"
extern DEVICE cpu_dev;
extern DEVICE ch_dev[NUM_CHAN];
extern DEVICE mt_dev[NUM_CHAN];
extern DEVICE drm_dev;
extern DEVICE dsk_dev;
extern DEVICE com_dev, coml_dev;
extern DEVICE cdr_dev, cdp_dev;
extern DEVICE lpt_dev;
extern DEVICE clk_dev;
extern UNIT cpu_unit;
extern REG cpu_reg[];
uint32 cvt_code_to_ascii (uint32 c, int32 sw);
uint32 cvt_ascii_to_code (uint32 c, int32 sw);
/* SCP data structures and interface routines
sim_name simulator name string
sim_PC pointer to saved PC register descriptor
sim_emax number of words for examine
sim_devices array of pointers to simulated devices
sim_stop_messages array of pointers to stop messages
sim_load binary loader
*/
char sim_name[] = "IBM 7094";
REG *sim_PC = &cpu_reg[0];
int32 sim_emax = 1;
DEVICE *sim_devices[] = {
&cpu_dev,
&clk_dev,
&ch_dev[0],
&ch_dev[1],
&ch_dev[2],
&ch_dev[3],
&ch_dev[4],
&ch_dev[5],
&ch_dev[6],
&ch_dev[7],
&mt_dev[0],
&mt_dev[1],
&mt_dev[2],
&mt_dev[3],
&mt_dev[4],
&mt_dev[5],
&mt_dev[6],
&mt_dev[7],
&cdr_dev,
&cdp_dev,
&lpt_dev,
&dsk_dev,
&drm_dev,
&com_dev,
&coml_dev,
NULL
};
char ch_bkpt_msg[] = "Channel A breakpoint, CLC: xxxxxx";
const char *sim_stop_messages[] = {
"Unknown error",
"HALT instruction",
"Breakpoint",
"Undefined instruction",
"Divide check",
"Nested XEC limit exceeded",
"Address stop",
"Non-existent channel",
"Illegal instruction for 7909 channel",
"Illegal instruction for non-7909 channel",
"Non-existent device",
"Undefined channel instruction",
"Write to protected device",
"Illegal instruction for device",
"Invalid 7631 track format",
"7750 buffer pool empty on input",
"7750 buffer pool empty on output",
"7750 invalid line number",
"7750 invalid message",
ch_bkpt_msg
};
/* Modify channel breakpoint message */
t_stat ch_bkpt (uint32 ch, uint32 clc)
{
ch_bkpt_msg[8] = 'A' + ch;
sprintf (&ch_bkpt_msg[27], "%06o", clc);
return STOP_CHBKPT;
}
/* Binary loader, not implemented */
t_stat sim_load (FILE *fileref, char *cptr, char *fnam, int flag)
{
return SCPE_NOFNC;
}
/* Symbol tables */
#define I_V_FL 39 /* inst class */
#define I_M_FL 017 /* class mask */
#define I_NOP 0000000000000000 /* no operand */
#define I_MXR 0010000000000000 /* addr(tag) */
#define I_MXN 0020000000000000 /* *addr(tag) */
#define I_MXV 0030000000000000 /* var mul/div */
#define I_MXC 0040000000000000 /* convert */
#define I_DNP 0050000000000000 /* decr, no oper */
#define I_DEC 0060000000000000 /* decrement */
#define I_SNS 0070000000000000 /* sense */
#define I_IMM 0100000000000000 /* 18b immediate */
#define I_TAG 0110000000000000 /* tag only */
#define I_IOX 0120000000000000 /* IO channel */
#define I_TCH 0130000000000000 /* transfer channel */
#define I_I9N 0140000000000000 /* 7909 with nostore */
#define I_I9S 0150000000000000 /* 7909 */
#define IFAKE_7607 0001000000000000 /* fake op extensions */
#define IFAKE_7909 0002000000000000
#define DFAKE (DMASK|IFAKE_7607|IFAKE_7909)
#define I_N_NOP 000
#define I_N_MXR 001
#define I_N_MXN 002
#define I_N_MXV 003
#define I_N_MXC 004
#define I_N_DNP 005
#define I_N_DEC 006
#define I_N_SNS 007
#define I_N_IMM 010
#define I_N_TAG 011
#define I_N_IOX 012
#define I_N_TCH 013
#define I_N_I9N 014
#define I_N_I9S 015
#define INST_P_XIT 0 /* exit */
#define INST_P_SKP 1 /* do not print */
#define INST_P_PRA 2 /* print always */
#define INST_P_PNZ 3 /* print if nz */
#define INST_P_PNT 4 /* print if nz, term */
static const t_uint64 masks[14] = {
03777700000000, 03777700000000,
03777700000000, 03777700000000,
03777400000000, 03700000000000,
03700000000000, 03777700077777,
03777700000000, 03777700000000,
03700000200000, 03700000200000,
03760000200000, 03740000200000 };
static const uint32 fld_max[14][3] = { /* addr,tag,decr limit */
{ INST_M_ADDR, INST_M_TAG, 0 },
{ INST_M_ADDR, INST_M_TAG, 0 },
{ INST_M_ADDR, INST_M_TAG, 0 },
{ INST_M_ADDR, INST_M_TAG, INST_M_VCNT },
{ INST_M_ADDR, INST_M_TAG, INST_M_CCNT },
{ INST_M_ADDR, INST_M_TAG, INST_M_DEC },
{ INST_M_ADDR, INST_M_TAG, INST_M_DEC },
{ 0, INST_M_TAG, 0 },
{ RMASK, 0, 0 },
{ INST_M_ADDR, INST_M_TAG, 0 },
{ INST_M_ADDR, 1, INST_M_DEC },
{ INST_M_ADDR, 1, 0 },
{ INST_M_ADDR, 1, 0 },
{ INST_M_ADDR, 1, 0 }
};
static const uint32 fld_fmt[14][3] = { /* addr,tag,decr print */
{ INST_P_PNT, INST_P_PNT, INST_P_XIT }, /* nop: all optional */
{ INST_P_PRA, INST_P_PNT, INST_P_XIT }, /* mxr: tag optional */
{ INST_P_PRA, INST_P_PNT, INST_P_XIT }, /* mxn: tag optional */
{ INST_P_PRA, INST_P_PNZ, INST_P_PRA }, /* mxv: tag optional */
{ INST_P_PRA, INST_P_PNZ, INST_P_PRA }, /* cvt: tag optional */
{ INST_P_PNT, INST_P_PNT, INST_P_PNT }, /* dnp: all optional */
{ INST_P_PRA, INST_P_PRA, INST_P_PRA }, /* dec: print all */
{ INST_P_SKP, INST_P_PNT, INST_P_XIT }, /* sns: skip addr, tag opt */
{ INST_P_PRA, INST_P_XIT, INST_P_XIT }, /* immediate: addr only */
{ INST_P_PNZ, INST_P_PRA, INST_P_XIT }, /* tag: addr optional */
{ INST_P_PRA, INST_P_PNZ, INST_P_PRA }, /* iox: tag optional */
{ INST_P_PRA, INST_P_PNT, INST_P_XIT }, /* tch: tag optional */
{ INST_P_PRA, INST_P_PNT, INST_P_XIT }, /* i9n: tag optional */
{ INST_P_PRA, INST_P_PNT, INST_P_XIT } /* i9s: tag optional */
};
static const t_uint64 ind_test[14] = {
0, 0, INST_IND, 0, 0, 0, 0,
0, 0, 0, CHI_IND, CHI_IND, CHI_IND, CHI_IND
};
static const char *opcode[] = {
"TXI", "TIX", "TXH",
"STR", "TNX", "TXL",
"HTR", "TRA", "TTR",
"CLM", "LBT", "CHS",
"SSP", "ENK", "IOT",
"COM", "ETM", "RND",
"FRN", "DCT", "RCT",
"LMTM", "SLF", "SLN1",
"SLN2", "SLN3", "SLN4",
"SWT1", "SWT2", "SWT3",
"SWT4", "SWT5", "SWT6",
"BTTA", "BTTB", "BTTC",
"BTTD", "BTTE", "BTTF",
"BTTG", "BTTH",
"RICA", "RICB", "RICC",
"RICD", "RICE", "RICF",
"RICG", "RICH",
"RDCA", "RDCB", "RDCC",
"RDCD", "RDCE", "RDCF",
"RDCG", "RDCH",
"TRCA", "TRCC",
"TRCE", "TRCG",
"TEFA", "TEFC",
"TEFE", "TEFG",
"TLQ", "IIA", "TIO",
"OAI", "PAI", "TIF",
"IIR", "RFT", "SIR",
"RNT", "RIR",
"TCOA", "TCOB", "TCOC",
"TCOD", "TCOE", "TCOF",
"TCOG", "TCOH", "TSX",
"TZE", "CVR", "TPL",
"XCA", "TOV",
"TQO", "TQP",
"MPY", "VLM", "VLM1",
"DVH", "DVP",
"VDH", "VDP",
"VDH2", "VDP2",
"FDH", "FDP",
"FMP", "DFMP",
"FAD", "DFAD",
"FSB", "DFSB",
"FAM", "DFAM",
"FSM", "DFSM",
"ANS", "ERA",
"CAS", "ACL",
"ADD", "ADM",
"SUB", "SBM",
"HPR", "IIS", "LDI",
"OSI", "DLD", "OFT",
"RIS", "ONT",
"CLA", "CLS",
"ZET", "XEC",
"LXA", "LAC",
"RCHA", "RCHC",
"RCHE", "RCHG",
"LCHA", "LCHC",
"LCHE", "LCHG",
"RSCA", "RSCC",
"RSCE", "RSCG",
"STCA", "STCC",
"STCE", "STCG",
"LDQ", "ENB",
"STZ", "STO", "SLW",
"STI", "STA", "STD",
"STT", "STP",
"SXA", "SCA",
"SCHA", "SCHC",
"SCHE", "SCHG",
"SCDA", "SCDC",
"SCDE", "SCDG",
"PAX", "PAC",
"PXA", "PCA",
"PSE", "NOP", "RDS",
"LLS", "BSR", "LRS",
"WRS", "ALS", "WEF",
"ARS", "REW", "AXT",
"SDN",
"CLM", "PBT", "EFTM",
"SSM", "LFTM", "ESTM",
"ECTM", "LTM", "LSNM",
"EMTM", "SLT1", "SLT2",
"SLT3", "SLT4",
"ETTA", "ETTB", "ETTC",
"ETTD", "ETTE", "ETTF",
"ETTG", "ETTH",
"ESNT",
"TRCB", "TRCD",
"TRCF", "TRCH",
"TEFB", "TEFD",
"TEFF", "TEFH",
"RIA", "PIA",
"IIL", "LFT", "SIL",
"LNT", "RIL",
"TCNA", "TCNB", "TCNC",
"TCND", "TCNE", "TCNF",
"TCNG", "TCNH",
"TNZ", "CVR", "TMI",
"XCL", "TNO", "CRQ",
"MPR", "DFDH", "DFDP",
"UFM", "DUFM",
"UFA", "DUFA",
"UFS", "DUFS",
"UAM", "DUAM",
"USM", "DUSM",
"ANA", "LAS",
"CAL", "ORA", "NZT",
"LXD", "LXC",
"RCHB", "RCHD",
"RCHF", "RCHH",
"LCHB", "LCHD",
"LCHF", "LCHH",
"RSCB", "RSCD",
"RSCF", "RSCH",
"STCB", "STCD",
"STCF", "STCH",
"STQ", "ORS", "DST",
"SLQ", "STL",
"SXD", "SCD",
"SCHB", "SCHD",
"SCHF", "SCHH",
"SCDB", "SCDD",
"SCDF", "SCDH",
"PDX", "PDC",
"PXD", "PCD",
"MSE", "LGL", "BSF",
"LGR", "RQL", "RUN",
"AXC",
"TIA", "TIB",
"LRI", "LPI",
"SEA", "SEB",
"IOCD", "IOCDN", "TCH",
"IORP", "IORPN",
"IORT", "IORTN",
"IOCP", "IOCPN",
"IOCT", "IOCTN",
"IOSP", "IOSPN",
"IOST", "IOSTN",
"WTR", "XMT",
"TCH", "LIPT",
"CTL", "CTLN",
"CTLR", "CTLRN",
"CTLW", "CTLWN",
"SNS",
"LAR", "SAR", "TWT",
"CPYP",
"CPYD", "TCM",
"LIP", "TDC", "LCC",
"SMS", "ICC",
NULL
};
static const t_uint64 opc_v[] = {
0100000000000+I_DEC, 0200000000000+I_DEC, 0300000000000+I_DEC,
0500000000000+I_DNP, 0600000000000+I_DEC, 0700000000000+I_DEC,
0000000000000+I_MXN, 0002000000000+I_MXN, 0002100000000+I_MXN,
0076000000000+I_SNS, 0076000000001+I_SNS, 0076000000002+I_SNS,
0076000000003+I_SNS, 0076000000004+I_SNS, 0076000000005+I_SNS,
0076000000006+I_SNS, 0076000000007+I_SNS, 0076000000010+I_SNS,
0076000000011+I_SNS, 0076000000012+I_SNS, 0076000000014+I_SNS,
0076000000016+I_SNS, 0076000000140+I_SNS, 0076000000141+I_SNS,
0076000000142+I_SNS, 0076000000143+I_SNS, 0076000000144+I_SNS,
0076000000161+I_SNS, 0076000000162+I_SNS, 0076000000163+I_SNS,
0076000000164+I_SNS, 0076000000165+I_SNS, 0076000000166+I_SNS,
0076000001000+I_SNS, 0076000002000+I_SNS, 0076000003000+I_SNS,
0076000004000+I_SNS, 0076000005000+I_SNS, 0076000006000+I_SNS,
0076000007000+I_SNS, 0076000010000+I_SNS,
0076000001350+I_SNS, 0076000002350+I_SNS, 0076000003350+I_SNS,
0076000004350+I_SNS, 0076000005350+I_SNS, 0076000006350+I_SNS,
0076000007350+I_SNS, 0076000010350+I_SNS,
0076000001352+I_SNS, 0076000002352+I_SNS, 0076000003352+I_SNS,
0076000004352+I_SNS, 0076000005352+I_SNS, 0076000006352+I_SNS,
0076000007352+I_SNS, 0076000010352+I_SNS,
0002200000000+I_MXN, 0002400000000+I_MXN,
0002600000000+I_MXN, 0002700000000+I_MXN,
0003000000000+I_MXN, 0003100000000+I_MXN,
0003200000000+I_MXN, 0003300000000+I_MXN,
0004000000000+I_MXN, 0004100000000+I_NOP, 0004200000000+I_MXR,
0004300000000+I_NOP, 0004400000000+I_NOP, 0004600000000+I_MXR,
0005100000000+I_IMM, 0005400000000+I_IMM, 0005500000000+I_IMM,
0005600000000+I_IMM, 0005700000000+I_IMM,
0006000000000+I_MXN, 0006100000000+I_MXN, 0006200000000+I_MXN,
0006300000000+I_MXN, 0006400000000+I_MXN, 0006500000000+I_MXN,
0006600000000+I_MXN, 0006700000000+I_MXN, 0007400000000+I_MXR,
0010000000000+I_MXN, 0011400000000+I_MXC, 0012000000000+I_MXN,
0013100000000+I_NOP, 0014000000000+I_MXN,
0016100000000+I_MXN, 0016200000000+I_MXN,
0020000000000+I_MXN, 0020400000000+I_MXV, 0020500000000+I_MXV,
0022000000000+I_MXN, 0022100000000+I_MXN,
0022400000000+I_MXV, 0022500000000+I_MXV,
0022600000000+I_MXV, 0022700000000+I_MXV,
0024000000000+I_MXN, 0024100000000+I_MXN,
0026000000000+I_MXN, 0026100000000+I_MXN,
0030000000000+I_MXN, 0030100000000+I_MXN,
0030200000000+I_MXN, 0030300000000+I_MXN,
0030400000000+I_MXN, 0030500000000+I_MXN,
0030600000000+I_MXN, 0030700000000+I_MXN,
0032000000000+I_MXN, 0032200000000+I_MXN,
0034000000000+I_MXN, 0036100000000+I_MXN,
0040000000000+I_MXN, 0040100000000+I_MXN,
0040200000000+I_MXN, 0440000000000+I_MXN,
0042000000000+I_NOP, 0044000000000+I_MXN, 0044100000000+I_MXN,
0044200000000+I_MXN, 0044300000000+I_MXN, 0044400000000+I_MXN,
0044500000000+I_MXN, 0044600000000+I_MXN,
0050000000000+I_MXN, 0050200000000+I_MXN,
0052000000000+I_MXN, 0052200000000+I_MXN,
0053400000000+I_MXR, 0053500000000+I_MXR,
0054000000000+I_MXN, 0054100000000+I_MXN,
0054200000000+I_MXN, 0054300000000+I_MXN,
0054400000000+I_MXN, 0054500000000+I_MXN,
0054600000000+I_MXN, 0054700000000+I_MXN,
0054000000000+I_MXN, 0054100000000+I_MXN,
0054200000000+I_MXN, 0054300000000+I_MXN,
0054400000000+I_MXN, 0054500000000+I_MXN,
0054600000000+I_MXN, 0054700000000+I_MXN,
0056000000000+I_MXN, 0056400000000+I_MXN,
0060000000000+I_MXN, 0060100000000+I_MXN, 0060200000000+I_MXN,
0060400000000+I_MXN, 0062100000000+I_MXN, 0062200000000+I_MXN,
0062500000000+I_MXN, 0063000000000+I_MXN,
0063400000000+I_MXR, 0063600000000+I_MXR,
0064000000000+I_MXN, 0064000000000+I_MXN,
0064200000000+I_MXN, 0064300000000+I_MXN,
0064400000000+I_MXN, 0064500000000+I_MXN,
0064600000000+I_MXN, 0064700000000+I_MXN,
0073400000000+I_TAG, 0073700000000+I_TAG,
0075400000000+I_TAG, 0075600000000+I_TAG,
0076000000000+I_MXR, 0076100000000+I_NOP, 0076200000000+I_MXR,
0076300000000+I_MXR, 0076400000000+I_MXR, 0076500000000+I_MXR,
0076600000000+I_MXR, 0076700000000+I_MXR, 0077000000000+I_MXR,
0077100000000+I_MXR, 0077200000000+I_MXR, 0077400000000+I_MXR,
0077600000000+I_MXR,
0476000000000+I_SNS, 0476000000001+I_SNS, 0476000000002+I_SNS,
0476000000003+I_SNS, 0476000000004+I_SNS, 0476000000005+I_SNS,
0476000000006+I_SNS, 0476000000007+I_SNS, 0476000000010+I_SNS,
0476000000016+I_SNS, 0476000000141+I_SNS, 0476000000142+I_SNS,
0476000000143+I_SNS, 0476000000144+I_SNS,
0476000001000+I_SNS, 0476000002000+I_SNS, 0476000003000+I_SNS,
0476000004000+I_SNS, 0476000005000+I_SNS, 0476000006000+I_SNS,
0476000007000+I_SNS, 0476000010000+I_SNS,
0402100000000+I_MXN,
0402200000000+I_MXN, 0402400000000+I_MXN,
0402600000000+I_MXN, 0402700000000+I_MXN,
0403000000000+I_MXN, 0403100000000+I_MXN,
0403200000000+I_MXN, 0403300000000+I_MXN,
0404200000000+I_NOP, 0404600000000+I_NOP,
0405100000000+I_IMM, 0405400000000+I_IMM, 0405500000000+I_IMM,
0405600000000+I_IMM, 0405700000000+I_IMM,
0406000000000+I_MXN, 0406100000000+I_MXN, 0406200000000+I_MXN,
0406300000000+I_MXN, 0406400000000+I_MXN, 0406500000000+I_MXN,
0406600000000+I_MXN, 0406700000000+I_MXN,
0410000000000+I_MXN, 0411400000000+I_MXC, 0412000000000+I_MXN,
0413000000000+I_NOP, 0414000000000+I_MXN, 0415400000000+I_MXC,
0420000000000+I_MXN, 0424000000000+I_MXN, 0424100000000+I_MXN,
0426000000000+I_MXN, 0426100000000+I_MXN,
0430000000000+I_MXN, 0430100000000+I_MXN,
0430200000000+I_MXN, 0430300000000+I_MXN,
0430400000000+I_MXN, 0430500000000+I_MXN,
0430600000000+I_MXN, 0430700000000+I_MXN,
0432000000000+I_MXN, 0434000000000+I_MXN,
0450000000000+I_MXN, 0450100000000+I_MXN, 0452000000000+I_MXN,
0453400000000+I_MXR, 0453500000000+I_MXR,
0454000000000+I_MXN, 0454100000000+I_MXN,
0454200000000+I_MXN, 0454300000000+I_MXN,
0454400000000+I_MXN, 0454500000000+I_MXN,
0454600000000+I_MXN, 0454700000000+I_MXN,
0454000000000+I_MXN, 0454100000000+I_MXN,
0454200000000+I_MXN, 0454300000000+I_MXN,
0454400000000+I_MXN, 0454500000000+I_MXN,
0454600000000+I_MXN, 0454700000000+I_MXN,
0460000000000+I_MXN, 0460200000000+I_MXN, 0460300000000+I_MXN,
0462000000000+I_MXN, 0462500000000+I_MXN,
0463400000000+I_MXR, 0463600000000+I_MXR,
0464000000000+I_MXN, 0464000000000+I_MXN,
0464200000000+I_MXN, 0464300000000+I_MXN,
0464400000000+I_MXN, 0464500000000+I_MXN,
0464600000000+I_MXN, 0464700000000+I_MXN,
0473400000000+I_TAG, 0473700000000+I_TAG,
0475400000000+I_TAG, 0475600000000+I_TAG,
0476000000000+I_MXR, 0476300000000+I_MXR, 0476400000000+I_MXR,
0476500000000+I_MXR, 0477300000000+I_MXR, 0477200000000+I_MXR,
0477400000000+I_MXR,
0010100000000+I_MXN, 0410100000000+I_MXN,
0056200000000+I_MXN, 0456400000000+I_MXN,
0476100000041+I_SNS, 0476100000042+I_SNS,
01000000000000+I_IOX, 01000000200000+I_IOX, 01100000000000+I_TCH,
01200000000000+I_IOX, 01200000200000+I_IOX,
01300000000000+I_IOX, 01300000200000+I_IOX,
01400000000000+I_IOX, 01400000200000+I_IOX,
01500000000000+I_IOX, 01500000200000+I_IOX,
01600000000000+I_IOX, 01600000200000+I_IOX,
01700000000000+I_IOX, 01700000200000+I_IOX,
02000000000000+I_TCH, 02000000200000+I_IOX,
02100000000000+I_TCH, 02100000200000+I_TCH,
02200000000000+I_I9N, 02220000000000+I_TCH,
02200000200000+I_I9N, 02220000200000+I_TCH,
02240000000000+I_I9N, 02260000000000+I_TCH,
02240000200000+I_I9N,
02300000000000+I_I9S, 02300000200000+I_I9S,
02340000000000+I_I9S,
02400000000000+I_IOX,
02500000000000+I_IOX, 02500000200000+I_IOX,
02600000200000+I_I9S, 02640000000000+I_I9S, 02640000200000+I_I9S,
02700000000000+I_I9S, 02700000200000+I_IOX,
0
};
/* Symbolic decode
Inputs:
*of = output stream
addr = current PC
*val = pointer to values
*uptr = pointer to unit
sw = switches
Outputs:
return = status code
*/
t_stat fprint_sym (FILE *of, t_addr addr, t_value *val,
UNIT *uptr, int32 sw)
{
uint32 i, j, k, l, fmt, c, fld[3];
DEVICE *dptr;
t_uint64 inst;
inst = val[0];
if (uptr == NULL) uptr = &cpu_unit;
dptr = find_dev_from_unit (uptr);
if (dptr == NULL) return SCPE_IERR;
if (sw & SWMASK ('C')) { /* character? */
c = (uint32) (inst & 077);
fprintf (of, "%c", cvt_code_to_ascii (c, sw));
return SCPE_OK;
}
if (sw & SWMASK ('S')) { /* string? */
for (i = 36; i > 0; i = i - 6) {
c = (uint32) ((inst >> (i - 6)) & 077);
fprintf (of, "%c", cvt_code_to_ascii (c, sw));
}
return SCPE_OK;
}
if (!(sw & (SWMASK ('M')|SWMASK ('I')|SWMASK ('N'))) || /* M, N or I? */
(dptr->dwidth != 36)) return SCPE_ARG;
/* Instruction decode */
fld[0] = ((uint32) inst & 0777777);
fld[1] = GET_TAG (inst); /* get 3 fields */
fld[2] = GET_DEC (inst);
if (sw & SWMASK ('I')) inst |= IFAKE_7607; /* decode as 7607? */
if (sw & SWMASK ('N')) inst |= IFAKE_7909; /* decode as 7909? */
for (i = 0; opc_v[i] > 0; i++) { /* loop thru ops */
j = (int32) ((opc_v[i] >> I_V_FL) & I_M_FL); /* get class */
if ((opc_v[i] & DFAKE) == (inst & masks[j])) { /* match? */
if (inst & ind_test[j]) /* indirect? */
fprintf (of, "%s*", opcode[i]);
else fprintf (of, "%s", opcode[i]); /* opcode */
for (k = 0; k < 3; k++) fld[k] = fld[k] & fld_max[j][k];
for (k = 0; k < 3; k++) { /* loop thru fields */
fmt = fld_fmt[j][k]; /* get format */
if (fmt == INST_P_XIT) return SCPE_OK;
switch (fmt) { /* case on format */
case INST_P_PNT: /* print nz, else term */
for (l = k, c = 0; l < 3; l++) c |= fld[k];
if (c == 0) return SCPE_OK;
case INST_P_PNZ: /* print non-zero */
fputc (k? ',': ' ', of);
if (fld[k]) fprintf (of, "%-o", fld[k]);
break;
case INST_P_PRA: /* print always */
fputc (k? ',': ' ', of);
fprintf (of, "%-o", fld[k]);
break;
case INST_P_SKP: /* skip */
break;
} /* end switch */
} /* end for k */
return SCPE_OK; /* done */
} /* end if */
} /* end for i */
return SCPE_ARG;
}
/* Convert character to code to ASCII
-b BCD
-a business-chain */
uint32 cvt_code_to_ascii (uint32 c, int32 sw)
{
if (sw & SWMASK ('B')) {
if (sw & SWMASK ('A')) return bcd_to_ascii_a[c];
else return bcd_to_ascii_h[c];
}
else if (sw & SWMASK ('A')) return nine_to_ascii_a[c];
else return nine_to_ascii_h[c];
}
/* Symbolic input
Inputs:
*cptr = pointer to input string
addr = current PC
uptr = pointer to unit
*val = pointer to output values
sw = switches
Outputs:
status = error status
*/
t_stat parse_sym (char *cptr, t_addr addr, UNIT *uptr, t_value *val, int32 sw)
{
uint32 i, j, c;
t_uint64 fld[3];
t_bool ind;
t_stat r;
char gbuf[CBUFSIZE];
while (isspace (*cptr)) cptr++;
if ((sw & SWMASK ('C')) || ((*cptr == '\'') && cptr++)) { /* character? */
if (cptr[0] == 0) return SCPE_ARG; /* must have 1 char */
val[0] = (t_value) cvt_ascii_to_code (cptr[0] & 0177, sw);
return SCPE_OK;
}
if ((sw & SWMASK ('S')) || ((*cptr == '"') && cptr++)) { /* sixbit string? */
if (cptr[0] == 0) return SCPE_ARG; /* must have 1 char */
for (i = 0; i < 6; i++) {
c = cptr[0] & 0177;
if (c) val[0] = (val[0] << 6) | ((t_value) cvt_ascii_to_code (c, sw));
else {
val[0] = val[0] << (6 * (6 - i));
break;
}
}
return SCPE_OK;
}
cptr = get_glyph (cptr, gbuf, 0); /* get opcode */
j = strlen (gbuf); /* get length */
if (gbuf[j - 1] == '*') { /* indirect? */
ind = TRUE;
gbuf[j - 1] = 0;
}
else ind = FALSE;
for (i = 0; (opcode[i] != NULL) && (strcmp (opcode[i], gbuf) != 0) ; i++) ;
if (opcode[i] == NULL) return SCPE_ARG;
j = (uint32) ((opc_v[i] >> I_V_FL) & I_M_FL); /* get class */
val[0] = opc_v[i] & DMASK;
if (ind) {
if (ind_test[j]) val[0] |= ind_test[j];
else return SCPE_ARG;
}
for (i = 0; i < 3; i++) fld[i] = 0; /* clear inputs */
for (i = 0; (i < 3) && *cptr; i++) { /* parse inputs */
if (i < 2) cptr = get_glyph (cptr, gbuf, ','); /* get glyph */
else cptr = get_glyph (cptr, gbuf, 0);
if (gbuf[0]) { /* anything? */
fld[i] = get_uint (gbuf, 8, fld_max[j][i], &r);
if ((r != SCPE_OK) || (fld_max[j][i] == 0)) return SCPE_ARG;
}
}
if (*cptr != 0) return SCPE_ARG; /* junk at end? */
val[0] = val[0] | fld[0] | (fld[1] << INST_V_TAG) | (fld[2] << INST_V_DEC);
return SCPE_OK;
}
/* Convert ASCII to character code
-b BCD */
uint32 cvt_ascii_to_code (uint32 c, int32 sw)
{
if (sw & SWMASK ('B')) return ascii_to_bcd[c];
else return ascii_to_nine[c];
}

View file

@ -1,6 +1,6 @@
/* id16_cpu.c: Interdata 16b CPU simulator /* id16_cpu.c: Interdata 16b CPU simulator
Copyright (c) 2000-2005, Robert M. Supnik Copyright (c) 2000-2006, Robert M. Supnik
Permission is hereby granted, free of charge, to any person obtaining a Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"), copy of this software and associated documentation files (the "Software"),
@ -25,6 +25,7 @@
cpu Interdata 16b CPU cpu Interdata 16b CPU
06-Feb-06 RMS Fixed bug in DH (found by Mark Hittinger)
22-Sep-05 RMS Fixed declarations (from Sterling Garwood) 22-Sep-05 RMS Fixed declarations (from Sterling Garwood)
25-Aug-05 RMS Fixed DH integer overflow cases 25-Aug-05 RMS Fixed DH integer overflow cases
16-Aug-05 RMS Fixed C++ declaration and cast problems 16-Aug-05 RMS Fixed C++ declaration and cast problems
@ -169,6 +170,7 @@ typedef struct {
uint16 opnd; uint16 opnd;
} InstHistory; } InstHistory;
#define PSW_GETMAP(x) (((x) >> PSW_V_MAP) & PSW_M_MAP)
#define SEXT16(x) (((x) & SIGN16)? ((int32) ((x) | 0xFFFF8000)): \ #define SEXT16(x) (((x) & SIGN16)? ((int32) ((x) | 0xFFFF8000)): \
((int32) ((x) & 0x7FFF))) ((int32) ((x) & 0x7FFF)))
#define CC_GL_16(x) if ((x) & SIGN16) cc = CC_L; \ #define CC_GL_16(x) if ((x) & SIGN16) cc = CC_L; \
@ -1058,7 +1060,7 @@ while (reason == 0) { /* loop until halted */
case 0x4D: /* DH - RXH */ case 0x4D: /* DH - RXH */
r1p1 = (r1 + 1) & 0xF; /* R1 + 1 */ r1p1 = (r1 + 1) & 0xF; /* R1 + 1 */
if ((opnd == 0) || if ((opnd == 0) ||
((R[r1] == 0x8000) && (R[r1p1] == 0) && (opnd = 0xFFFF))) { ((R[r1] == 0x8000) && (R[r1p1] == 0) && (opnd == 0xFFFF))) {
if (PSW & PSW_AFI) /* div fault enabled? */ if (PSW & PSW_AFI) /* div fault enabled? */
cc = swap_psw (AFIPSW, cc); /* swap PSW */ cc = swap_psw (AFIPSW, cc); /* swap PSW */
break; break;

View file

@ -1,6 +1,6 @@
/* id32_cpu.c: Interdata 32b CPU simulator /* id32_cpu.c: Interdata 32b CPU simulator
Copyright (c) 2000-2005, Robert M. Supnik Copyright (c) 2000-2006, Robert M. Supnik
Permission is hereby granted, free of charge, to any person obtaining a Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"), copy of this software and associated documentation files (the "Software"),
@ -25,6 +25,8 @@
cpu Interdata 32b CPU cpu Interdata 32b CPU
09-Mar-06 RMS Added 8 register bank support for 8/32
06-Feb-06 RMS Fixed bug in DH (found by Mark Hittinger)
22-Sep-05 RMS Fixed declarations (from Sterling Garwood) 22-Sep-05 RMS Fixed declarations (from Sterling Garwood)
16-Aug-05 RMS Fixed C++ declaration and cast problems 16-Aug-05 RMS Fixed C++ declaration and cast problems
10-Mar-05 RMS Fixed bug in initial memory allocation 10-Mar-05 RMS Fixed bug in initial memory allocation
@ -156,7 +158,7 @@
#define PCQ_MASK (PCQ_SIZE - 1) #define PCQ_MASK (PCQ_SIZE - 1)
#define PCQ_ENTRY pcq[pcq_p = (pcq_p - 1) & PCQ_MASK] = oPC #define PCQ_ENTRY pcq[pcq_p = (pcq_p - 1) & PCQ_MASK] = oPC
#define VAMASK VAMASK32 #define VAMASK VAMASK32
#define NRSETS 2 /* 2 gen reg sets */ #define NRSETS 8 /* up to 8 reg sets */
#define PSW_MASK PSW_x32 #define PSW_MASK PSW_x32
#define ABORT(val) longjmp (save_env, (val)) #define ABORT(val) longjmp (save_env, (val))
#define MPRO (-1) #define MPRO (-1)
@ -164,9 +166,11 @@
#define UNIT_V_MSIZE (UNIT_V_UF + 0) /* dummy mask */ #define UNIT_V_MSIZE (UNIT_V_UF + 0) /* dummy mask */
#define UNIT_V_DPFP (UNIT_V_UF + 1) #define UNIT_V_DPFP (UNIT_V_UF + 1)
#define UNIT_V_832 (UNIT_V_UF + 2) #define UNIT_V_832 (UNIT_V_UF + 2)
#define UNIT_V_8RS (UNIT_V_UF + 3)
#define UNIT_MSIZE (1 << UNIT_V_MSIZE) #define UNIT_MSIZE (1 << UNIT_V_MSIZE)
#define UNIT_DPFP (1 << UNIT_V_DPFP) #define UNIT_DPFP (1 << UNIT_V_DPFP)
#define UNIT_832 (1 << UNIT_V_832) #define UNIT_832 (1 << UNIT_V_832)
#define UNIT_8RS (1 << UNIT_V_8RS)
#define UNIT_TYPE (UNIT_DPFP | UNIT_832) #define UNIT_TYPE (UNIT_DPFP | UNIT_832)
#define HIST_PC 0x40000000 #define HIST_PC 0x40000000
@ -183,6 +187,7 @@ typedef struct {
uint32 opnd; uint32 opnd;
} InstHistory; } InstHistory;
#define PSW_GETREG(x) (((x) >> PSW_V_REG) & psw_reg_mask)
#define SEXT32(x) (((x) & SIGN32)? ((int32) ((x) | ~0x7FFFFFFF)): \ #define SEXT32(x) (((x) & SIGN32)? ((int32) ((x) | ~0x7FFFFFFF)): \
((int32) ((x) & 0x7FFFFFFF))) ((int32) ((x) & 0x7FFFFFFF)))
#define SEXT16(x) (((x) & SIGN16)? ((int32) ((x) | ~0x7FFF)): \ #define SEXT16(x) (((x) & SIGN16)? ((int32) ((x) | ~0x7FFF)): \
@ -235,6 +240,7 @@ uint32 fp_in_hwre = 0; /* ucode vs hwre fp */
uint32 pawidth = PAWIDTH32; /* addr mask */ uint32 pawidth = PAWIDTH32; /* addr mask */
uint32 hst_p = 0; /* history pointer */ uint32 hst_p = 0; /* history pointer */
uint32 hst_lnt = 0; /* history length */ uint32 hst_lnt = 0; /* history length */
uint32 psw_reg_mask = 1; /* PSW reg mask */
InstHistory *hst = NULL; /* instruction history */ InstHistory *hst = NULL; /* instruction history */
jmp_buf save_env; /* abort handler */ jmp_buf save_env; /* abort handler */
struct BlockIO blk_io; /* block I/O status */ struct BlockIO blk_io; /* block I/O status */
@ -565,10 +571,14 @@ MTAB cpu_mod[] = {
{ UNIT_MSIZE, 262144, NULL, "256K", &cpu_set_size }, { UNIT_MSIZE, 262144, NULL, "256K", &cpu_set_size },
{ UNIT_MSIZE, 524288, NULL, "512K", &cpu_set_size }, { UNIT_MSIZE, 524288, NULL, "512K", &cpu_set_size },
{ UNIT_MSIZE, 1048756, NULL, "1M", &cpu_set_size }, { UNIT_MSIZE, 1048756, NULL, "1M", &cpu_set_size },
{ UNIT_TYPE, 0, "7/32, single precision fp", "732", NULL }, { UNIT_8RS|UNIT_TYPE, 0, NULL, "732", NULL },
{ UNIT_DPFP, UNIT_DPFP, NULL, "DPFP", NULL }, { UNIT_DPFP, UNIT_DPFP, NULL, "DPFP", NULL },
{ UNIT_TYPE, 0, "7/32, single precision fp", "732", NULL },
{ UNIT_TYPE, UNIT_DPFP, "7/32, double precision fp", NULL, NULL }, { UNIT_TYPE, UNIT_DPFP, "7/32, double precision fp", NULL, NULL },
{ UNIT_TYPE, UNIT_DPFP | UNIT_832, "8/32", "832", NULL }, { UNIT_8RS|UNIT_TYPE, UNIT_8RS|UNIT_DPFP|UNIT_832, NULL, "832", NULL },
{ UNIT_8RS, 0, NULL, "2RS", NULL },
{ UNIT_8RS|UNIT_TYPE, UNIT_8RS|UNIT_DPFP|UNIT_832, "832, 8 register sets", NULL, NULL },
{ UNIT_8RS|UNIT_TYPE, UNIT_DPFP|UNIT_832, "832, 2 register sets", NULL, NULL },
{ MTAB_XTD|MTAB_VDV|MTAB_NMO, 0, NULL, "CONSINT", { MTAB_XTD|MTAB_VDV|MTAB_NMO, 0, NULL, "CONSINT",
&cpu_set_consint, NULL, NULL }, &cpu_set_consint, NULL, NULL },
{ MTAB_XTD|MTAB_VDV|MTAB_NMO|MTAB_SHP, 0, "HISTORY", "HISTORY", { MTAB_XTD|MTAB_VDV|MTAB_NMO|MTAB_SHP, 0, "HISTORY", "HISTORY",
@ -608,6 +618,8 @@ else {
fp_in_hwre = 0; /* fp in ucode */ fp_in_hwre = 0; /* fp in ucode */
dec_flgs = OP_DPF; /* sp only */ dec_flgs = OP_DPF; /* sp only */
} }
if (cpu_unit.flags & UNIT_8RS) psw_reg_mask = 7; /* 8 register sets */
else psw_reg_mask = 1; /* 2 register sets */
int_eval (); /* eval interrupts */ int_eval (); /* eval interrupts */
cc = newPSW (PSW & PSW_MASK); /* split PSW, eval wait */ cc = newPSW (PSW & PSW_MASK); /* split PSW, eval wait */
sim_rtcn_init (lfc_unit.wait, TMR_LFC); /* init clock */ sim_rtcn_init (lfc_unit.wait, TMR_LFC); /* init clock */
@ -1223,7 +1235,7 @@ while (reason == 0) { /* loop until halted */
case 0x4D: /* DH - RXH */ case 0x4D: /* DH - RXH */
opnd = opnd & DMASK16; /* force HW opnd */ opnd = opnd & DMASK16; /* force HW opnd */
if ((opnd == 0) || /* div by zero? */ if ((opnd == 0) || /* div by zero? */
((R[r1] == 0x80000000) && (opnd = 0xFFFF))) { ((R[r1] == 0x80000000) && (opnd == 0xFFFF))) {
if (PSW & PSW_AFI) /* div fault enabled? */ if (PSW & PSW_AFI) /* div fault enabled? */
cc = exception (AFIPSW, cc, 0); /* exception */ cc = exception (AFIPSW, cc, 0); /* exception */
break; break;

View file

@ -1,6 +1,6 @@
/* id_defs.h: Interdata 16b/32b simulator definitions /* id_defs.h: Interdata 16b/32b simulator definitions
Copyright (c) 2000-2005, Robert M. Supnik Copyright (c) 2000-2006, Robert M. Supnik
Permission is hereby granted, free of charge, to any person obtaining a Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"), copy of this software and associated documentation files (the "Software"),
@ -26,6 +26,7 @@
The author gratefully acknowledges the help of Carl Friend and Al Kossow, The author gratefully acknowledges the help of Carl Friend and Al Kossow,
who provided key documents about the Interdata product line. who provided key documents about the Interdata product line.
09-Mar-06 RMS Increased register sets to architectural limit
25-Jan-04 RMS Removed local logging support 25-Jan-04 RMS Removed local logging support
22-Sep-03 RMS Added additional instruction decode types 22-Sep-03 RMS Added additional instruction decode types
21-Jun-03 RMS Changed subroutine argument for ARM compiler conflict 21-Jun-03 RMS Changed subroutine argument for ARM compiler conflict
@ -65,9 +66,9 @@
#if defined (IFP_IN_MEM) #if defined (IFP_IN_MEM)
#define ReadFReg(r) (fp_in_hwre? \ #define ReadFReg(r) (fp_in_hwre? \
F[(r) >> 1]: ReadF (((r) << 1) & ~3, P)) F[(r) >> 1]: ReadF (((r) << 1) & ~3, P))
#define WriteFReg(r,v) if (fp_in_hwre) F[(r) >> 1] = (v); \ #define WriteFReg(r,v) if (fp_in_hwre) F[(r) >> 1] = (v); \
else WriteF (((r) << 1) & ~3, (v), P) else WriteF (((r) << 1) & ~3, (v), P)
#else #else
#define ReadFReg(r) (F[(r) >> 1]) #define ReadFReg(r) (F[(r) >> 1])
#define WriteFReg(r,v) F[(r) >> 1] = (v) #define WriteFReg(r,v) F[(r) >> 1] = (v)
@ -114,13 +115,11 @@ typedef struct {
#define PSW_M_MAP 0xF #define PSW_M_MAP 0xF
#define PSW_MAP (PSW_M_MAP << PSW_V_MAP) #define PSW_MAP (PSW_M_MAP << PSW_V_MAP)
#define PSW_V_REG 4 /* reg set, 32b */ #define PSW_V_REG 4 /* reg set, 32b */
#define PSW_M_REG 0x1 #define PSW_M_REG 0xF
#define PSW_ID4 0xF40F /* I3, I4 PSW */ #define PSW_ID4 0xF40F /* I3, I4 PSW */
#define PSW_x16 0xFF0F /* 7/16, 8/16 PSW */ #define PSW_x16 0xFF0F /* 7/16, 8/16 PSW */
#define PSW_816E 0xFFFF /* 8/16E PSW */ #define PSW_816E 0xFFFF /* 8/16E PSW */
#define PSW_x32 0xFFFF /* 7/32, 8/32 PSW */ #define PSW_x32 0xFFFF /* 7/32, 8/32 PSW */
#define PSW_GETMAP(x) (((x) >> PSW_V_MAP) & PSW_M_MAP)
#define PSW_GETREG(x) (((x) >> PSW_V_REG) & PSW_M_REG)
#define MCKOPSW 0x20 /* mchk old PSW, 32b */ #define MCKOPSW 0x20 /* mchk old PSW, 32b */
#define FPFPSW 0x28 /* flt fault PSW, 16b */ #define FPFPSW 0x28 /* flt fault PSW, 16b */

View file

@ -655,7 +655,7 @@ sim> boot mt0
Breakpoint, PC: 00A00 (B A5E) Breakpoint, PC: 00A00 (B A5E)
sim> d -w a10 0101 ; patch for TTY console sim> d -h a10 0202 ; patch for TTY console
sim> att dm0 foo.dsk sim> att dm0 foo.dsk
sim> att dm1 foo1.dsk sim> att dm1 foo1.dsk
sim> c sim> c
@ -904,4 +904,8 @@ Bugs found
92. IDC: read with invalid head sets ACF, not DTE 92. IDC: read with invalid head sets ACF, not DTE
93. DP, IDC: write with cylinder overflow advanced selch pointer 93. DP, IDC: write with cylinder overflow advanced selch pointer
94. MT: read error must stop selector channel (if active) 94. MT: read error must stop selector channel (if active)
95. IDC: xx000000 to controller or drive are NOP's, not invalid commands
96. IDC: WD/WH use standard Interdata write pointers
97. SELCH: GO preserves EXA and SSTA
98. CPU: DH overflow checking broken

File diff suppressed because it is too large Load diff

View file

@ -505,7 +505,7 @@ if (OP_DPFP (op)) { /* double precision? */
} }
else { else {
WriteFReg (r1, hi); WriteFReg (r1, hi);
} }
return cc; return cc;
} }
@ -527,6 +527,6 @@ if (OP_DPFP (op)) { /* double precision? */
} }
else { else {
WriteFReg (r1, fop->h); WriteFReg (r1, fop->h);
} }
return cc; return cc;
} }

View file

@ -1,6 +1,6 @@
/* id_idc.c: Interdata MSM/IDC disk controller simulator /* id_idc.c: Interdata MSM/IDC disk controller simulator
Copyright (c) 2001-2005, Robert M. Supnik Copyright (c) 2001-2006, Robert M. Supnik
Permission is hereby granted, free of charge, to any person obtaining a Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"), copy of this software and associated documentation files (the "Software"),
@ -25,6 +25,8 @@
idc MSM/IDC disk controller idc MSM/IDC disk controller
03-Apr-06 RMS Fixed WD/WH handling (found by Davis Johnson)
30-Mar-06 RMS Fixed bug, nop command should be ignored (found by Davis Johnson)
25-Apr-03 RMS Revised for extended file support 25-Apr-03 RMS Revised for extended file support
16-Feb-03 RMS Fixed read to test transfer ok before selch operation 16-Feb-03 RMS Fixed read to test transfer ok before selch operation
@ -199,14 +201,16 @@ extern uint32 int_req[INTSZ], int_enb[INTSZ];
uint8 idcxb[IDC_NUMBY * 3]; /* xfer buffer */ uint8 idcxb[IDC_NUMBY * 3]; /* xfer buffer */
uint32 idc_bptr = 0; /* buffer ptr */ uint32 idc_bptr = 0; /* buffer ptr */
uint32 idc_wdptr = 0; /* ctrl write data ptr */
uint32 idc_db = 0; /* ctrl buffer */ uint32 idc_db = 0; /* ctrl buffer */
uint32 idd_db = 0; /* drive buffer */
uint32 idc_sta = 0; /* ctrl status */ uint32 idc_sta = 0; /* ctrl status */
uint32 idc_sec = 0; /* sector */ uint32 idc_sec = 0; /* sector */
uint32 idc_hcyl = 0; /* head/cyl */ uint32 idc_hcyl = 0; /* head/cyl */
uint32 idc_svun = 0; /* most recent unit */ uint32 idc_svun = 0; /* most recent unit */
uint32 idc_1st = 0; /* first byte */ uint32 idc_1st = 0; /* first byte */
uint32 idc_arm = 0; /* ctrl armed */ uint32 idc_arm = 0; /* ctrl armed */
uint32 idd_db = 0; /* drive buffer */
uint32 idd_wdptr = 0; /* drive write data ptr */
uint32 idd_arm[ID_NUMDR] = { 0 }; /* drives armed */ uint32 idd_arm[ID_NUMDR] = { 0 }; /* drives armed */
uint16 idd_dcy[ID_NUMDR] = { 0 }; /* desired cyl */ uint16 idd_dcy[ID_NUMDR] = { 0 }; /* desired cyl */
uint32 idd_sirq = 0; /* drive saved irq */ uint32 idd_sirq = 0; /* drive saved irq */
@ -221,6 +225,7 @@ t_stat idc_svc (UNIT *uptr);
t_stat idc_reset (DEVICE *dptr); t_stat idc_reset (DEVICE *dptr);
t_stat idc_attach (UNIT *uptr, char *cptr); t_stat idc_attach (UNIT *uptr, char *cptr);
t_stat idc_set_size (UNIT *uptr, int32 val, char *cptr, void *desc); t_stat idc_set_size (UNIT *uptr, int32 val, char *cptr, void *desc);
void idc_wd_byte (uint32 dat);
t_stat idc_rds (UNIT *uptr); t_stat idc_rds (UNIT *uptr);
t_stat idc_wds (UNIT *uptr); t_stat idc_wds (UNIT *uptr);
t_bool idc_dter (UNIT *uptr, uint32 first); t_bool idc_dter (UNIT *uptr, uint32 first);
@ -259,6 +264,8 @@ REG idc_reg[] = {
{ BRDATA (DBUF, idcxb, 16, 8, IDC_NUMBY * 3) }, { BRDATA (DBUF, idcxb, 16, 8, IDC_NUMBY * 3) },
{ HRDATA (DBPTR, idc_bptr, 10), REG_RO }, { HRDATA (DBPTR, idc_bptr, 10), REG_RO },
{ FLDATA (FIRST, idc_1st, 0) }, { FLDATA (FIRST, idc_1st, 0) },
{ HRDATA (CWDPTR, idc_wdptr, 2) },
{ HRDATA (DWDPTR, idc_wdptr, 1) },
{ GRDATA (IREQ, int_req[l_IDC], 16, ID_NUMDR + 1, i_IDC) }, { GRDATA (IREQ, int_req[l_IDC], 16, ID_NUMDR + 1, i_IDC) },
{ GRDATA (IENB, int_enb[l_IDC], 16, ID_NUMDR + 1, i_IDC) }, { GRDATA (IENB, int_enb[l_IDC], 16, ID_NUMDR + 1, i_IDC) },
{ GRDATA (SIREQ, idd_sirq, 16, ID_NUMDR, i_IDC + 1), REG_RO }, { GRDATA (SIREQ, idd_sirq, 16, ID_NUMDR, i_IDC + 1), REG_RO },
@ -358,11 +365,12 @@ switch (op) { /* case IO op */
return 0; /* return data */ return 0; /* return data */
case IO_WD: /* write data */ case IO_WD: /* write data */
idc_sec = dat; /* sector */ idc_wd_byte (dat); /* one byte only */
break; break;
case IO_WH: /* write halfword */ case IO_WH: /* write halfword */
idc_hcyl = dat; /* head/cylinder */ idc_wd_byte (dat >> 8); /* high byte */
idc_wd_byte (dat); /* low byte */
break; break;
case IO_SS: /* status */ case IO_SS: /* status */
@ -372,15 +380,17 @@ switch (op) { /* case IO op */
case IO_OC: /* command */ case IO_OC: /* command */
idc_arm = int_chg (v_IDC, dat, idc_arm); /* upd int ctrl */ idc_arm = int_chg (v_IDC, dat, idc_arm); /* upd int ctrl */
idc_wdptr = 0; /* init ptr */
f = dat & CMC_MASK; /* get cmd */ f = dat & CMC_MASK; /* get cmd */
uptr = idc_dev.units + idc_svun; /* get unit */ uptr = idc_dev.units + idc_svun; /* get unit */
if (f & CMC_CLR) { /* clear? */ if (f & CMC_CLR) { /* clear? */
idc_reset (&idc_dev); /* reset world */ idc_reset (&idc_dev); /* reset world */
break; break;
} }
if (!(idc_sta & STC_IDL) || /* if !idle, */ if ((f == 0) || /* if nop, */
sim_is_active (uptr) || /* unit busy, */ (f == CMC_EXP0) || /* expg, */
(f == CMC_EXP0)) break; /* expg, ignore */ !(idc_sta & STC_IDL) || /* !idle, */
sim_is_active (uptr)) break; /* unit busy, ignore */
idc_sta = STA_BSY; /* bsy=1,idl,err=0 */ idc_sta = STA_BSY; /* bsy=1,idl,err=0 */
idc_1st = 1; /* xfr not started */ idc_1st = 1; /* xfr not started */
idc_bptr = 0; /* buffer empty */ idc_bptr = 0; /* buffer empty */
@ -394,11 +404,37 @@ switch (op) { /* case IO op */
return 0; return 0;
} }
/* Process WD/WH data */
void idc_wd_byte (uint32 dat)
{
dat = dat & 0xFF;
switch (idc_wdptr) {
case 0: /* byte 0 = sector */
idc_sec = dat;
idc_wdptr++;
break;
case 1: /* byte 1 = high hd/cyl */
idc_hcyl = (idc_hcyl & 0xFF) | (dat << 8);
idc_wdptr++;
break;
case 2: /* byte 2 = low hd/cyl */
idc_hcyl = (idc_hcyl & 0xFF00) | dat;
idc_wdptr = 0;
break;
}
return;
}
/* Drives: IO routine */ /* Drives: IO routine */
uint32 id (uint32 dev, uint32 op, uint32 dat) uint32 id (uint32 dev, uint32 op, uint32 dat)
{ {
uint32 t, u; uint32 t, u, f;
UNIT *uptr; UNIT *uptr;
if (dev == idc_dib.dno) return idc (dev, op, dat); /* controller? */ if (dev == idc_dib.dno) return idc (dev, op, dat); /* controller? */
@ -408,15 +444,17 @@ switch (op) { /* case IO op */
case IO_ADR: /* select */ case IO_ADR: /* select */
if (idc_sta & STC_IDL) idc_svun = u; /* idle? save unit */ if (idc_sta & STC_IDL) idc_svun = u; /* idle? save unit */
return HW; /* byte only */ return BY; /* byte only */
case IO_RD: /* read data */ case IO_RD: /* read data */
case IO_RH: case IO_RH:
return 0; return 0;
case IO_WD: /* write data */ case IO_WD: /* write data */
case IO_WH: /* write halfword */ if (idd_wdptr & 1) /* low byte? */
idd_db = dat; /* save data */ idd_db = (idd_db & 0xFF00) | dat;
else idd_db = (idd_db & 0xFF) | (dat << 8); /* no, high */
idd_wdptr = idd_wdptr ^ 1; /* other byte */
break; break;
case IO_SS: /* status */ case IO_SS: /* status */
@ -430,12 +468,15 @@ switch (op) { /* case IO op */
case IO_OC: /* command */ case IO_OC: /* command */
idd_arm[u] = int_chg (v_IDC + u + 1, dat, idd_arm[u]); idd_arm[u] = int_chg (v_IDC + u + 1, dat, idd_arm[u]);
idd_wdptr = 0; /* init ptr */
if (idd_arm[u] == 0) /* disarmed? */ if (idd_arm[u] == 0) /* disarmed? */
idd_sirq &= ~(1 << (v_IDC + u + 1)); /* clr saved req */ idd_sirq &= ~(1 << (v_IDC + u + 1)); /* clr saved req */
if (sim_is_active (uptr) || /* if busy or */ f = dat & CMC_MASK; /* get cmd */
!(idc_sta & STC_IDL)) break; /* !idle, ignore */ if ((f == 0) || /* if nop, */
if ((dat & CMC_MASK) == CMDX_MASK) break; /* ignore 0x30 */ (f == CMDX_MASK) || /* 0x30, */
uptr->FNC = (dat & CMC_MASK) | CMC_DRV; /* save cmd */ !(idc_sta & STC_IDL) || /* !idle, */
sim_is_active (uptr)) break; /* unit busy, ignore */
uptr->FNC = f | CMC_DRV; /* save cmd */
idc_sta = idc_sta & ~STC_IDL; /* clr idle */ idc_sta = idc_sta & ~STC_IDL; /* clr idle */
sim_activate (uptr, idc_ctime); /* schedule */ sim_activate (uptr, idc_ctime); /* schedule */
break; break;
@ -687,6 +728,8 @@ uint32 u;
UNIT *uptr; UNIT *uptr;
idc_sta = STC_IDL | STA_BSY; /* idle, busy */ idc_sta = STC_IDL | STA_BSY; /* idle, busy */
idc_wdptr = 0;
idd_wdptr = 0;
idc_1st = 0; /* clear flag */ idc_1st = 0; /* clear flag */
idc_svun = idc_db = 0; /* clear unit, buf */ idc_svun = idc_db = 0; /* clear unit, buf */
idc_sec = 0; /* clear addr */ idc_sec = 0; /* clear addr */

View file

@ -1,6 +1,6 @@
/* id_io.c: Interdata CPU-independent I/O routines /* id_io.c: Interdata CPU-independent I/O routines
Copyright (c) 2001-2005, Robert M. Supnik Copyright (c) 2001-2006, Robert M. Supnik
Permission is hereby granted, free of charge, to any person obtaining a Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"), copy of this software and associated documentation files (the "Software"),
@ -23,6 +23,7 @@
used in advertising or otherwise to promote the sale, use or other dealings used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from Robert M Supnik. in this Software without prior written authorization from Robert M Supnik.
30-Mar-06 RMS Fixed bug, GO preserves EXA and SSTA (found by Davis Johnson)
21-Jun-03 RMS Changed subroutine argument for ARM compiler conflict 21-Jun-03 RMS Changed subroutine argument for ARM compiler conflict
Interdata I/O devices are defined by a device information block: Interdata I/O devices are defined by a device information block:
@ -209,7 +210,7 @@ switch (op) { /* case IO op */
sch_wdc[ch] = 0; sch_wdc[ch] = 0;
} }
else if (dat & SCHC_GO) { /* go? */ else if (dat & SCHC_GO) { /* go? */
sch_cmd[ch] = dat & (SCHC_GO | SCHC_RD); sch_cmd[ch] = dat & (SCHC_EXA | SCHC_SSTA| SCHC_GO | SCHC_RD);
if (sch_wdc[ch] <= 4) { /* 4 bytes? */ if (sch_wdc[ch] <= 4) { /* 4 bytes? */
sch_sa[ch] = (sch_sa[ch] & PAMASK16) | bank; /* 16b addr */ sch_sa[ch] = (sch_sa[ch] & PAMASK16) | bank; /* 16b addr */
sch_ea[ch] = (sch_ea[ch] & PAMASK16) | bank; sch_ea[ch] = (sch_ea[ch] & PAMASK16) | bank;

View file

@ -1,6 +1,6 @@
/* id_mt.c: Interdata magnetic tape simulator /* id_mt.c: Interdata magnetic tape simulator
Copyright (c) 2001-2005, Robert M Supnik Copyright (c) 2001-2006, Robert M Supnik
Permission is hereby granted, free of charge, to any person obtaining a Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"), copy of this software and associated documentation files (the "Software"),
@ -25,6 +25,7 @@
mt M46-494 dual density 9-track magtape controller mt M46-494 dual density 9-track magtape controller
16-Feb-06 RMS Added tape capacity checking
18-Mar-05 RMS Added attached test to detach routine 18-Mar-05 RMS Added attached test to detach routine
07-Dec-04 RMS Added read-only file support 07-Dec-04 RMS Added read-only file support
25-Apr-03 RMS Revised for extended file support 25-Apr-03 RMS Revised for extended file support
@ -153,6 +154,8 @@ MTAB mt_mod[] = {
{ MTUF_WLK, MTUF_WLK, "write locked", "LOCKED", NULL }, { MTUF_WLK, MTUF_WLK, "write locked", "LOCKED", NULL },
{ MTAB_XTD|MTAB_VUN, 0, "FORMAT", "FORMAT", { MTAB_XTD|MTAB_VUN, 0, "FORMAT", "FORMAT",
&sim_tape_set_fmt, &sim_tape_show_fmt, NULL }, &sim_tape_set_fmt, &sim_tape_show_fmt, NULL },
{ MTAB_XTD|MTAB_VUN, 0, "CAPACITY", "CAPACITY",
&sim_tape_set_capac, &sim_tape_show_capac, NULL },
{ MTAB_XTD|MTAB_VDV, 0, "DEVNO", "DEVNO", { MTAB_XTD|MTAB_VDV, 0, "DEVNO", "DEVNO",
&set_dev, &show_dev, NULL }, &set_dev, &show_dev, NULL },
{ MTAB_XTD|MTAB_VDV, 0, "SELCH", "SELCH", { MTAB_XTD|MTAB_VDV, 0, "SELCH", "SELCH",
@ -260,6 +263,7 @@ uint32 i;
int32 u = uptr - mt_dev.units; int32 u = uptr - mt_dev.units;
uint32 dev = mt_dib.dno + (u * o_MT0); uint32 dev = mt_dib.dno + (u * o_MT0);
t_mtrlnt tbc; t_mtrlnt tbc;
t_bool passed_eot;
t_stat st, r = SCPE_OK; t_stat st, r = SCPE_OK;
if ((uptr->flags & UNIT_ATT) == 0) { /* not attached? */ if ((uptr->flags & UNIT_ATT) == 0) { /* not attached? */
@ -273,7 +277,7 @@ if ((uptr->flags & UNIT_ATT) == 0) { /* not attached? */
if (uptr->UCMD & MTC_STOP2) { /* stop, gen NMTN? */ if (uptr->UCMD & MTC_STOP2) { /* stop, gen NMTN? */
uptr->UCMD = 0; /* clr cmd */ uptr->UCMD = 0; /* clr cmd */
uptr->UST = STA_NMTN; /* set nmtn, not eot */ uptr->UST = uptr->UST | STA_NMTN; /* set nmtn */
mt_xfr = 0; /* clr xfr */ mt_xfr = 0; /* clr xfr */
if (mt_arm[u]) SET_INT (v_MT + u); /* set intr */ if (mt_arm[u]) SET_INT (v_MT + u); /* set intr */
return SCPE_OK; return SCPE_OK;
@ -287,6 +291,7 @@ if (uptr->UCMD & MTC_STOP1) { /* stop, gen EOM? */
return SCPE_OK; return SCPE_OK;
} }
passed_eot = sim_tape_eot (uptr); /* passed EOT? */
switch (uptr->UCMD) { /* case on function */ switch (uptr->UCMD) { /* case on function */
case MTC_REW: /* rewind */ case MTC_REW: /* rewind */
@ -388,6 +393,8 @@ switch (uptr->UCMD) { /* case on function */
break; break;
} /* end case */ } /* end case */
if (!passed_eot && sim_tape_eot (uptr)) /* just passed EOT? */
uptr->UST = uptr->UST | STA_EOT;
uptr->UCMD = uptr->UCMD | MTC_STOP1; /* set stop stage 1 */ uptr->UCMD = uptr->UCMD | MTC_STOP1; /* set stop stage 1 */
sim_activate (uptr, mt_rtime); /* schedule */ sim_activate (uptr, mt_rtime); /* schedule */
return r; return r;

View file

@ -1,465 +0,0 @@
To: Users
From: Bob Supnik
Subj: LGP Simulator Usage
Date: 15-Feb-2004
COPYRIGHT NOTICE
The following copyright notice applies to both the SIMH source and binary:
Original code published in 1993-2004, written by Robert M Supnik
Copyright (c) 1993-2004, Robert M Supnik
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Except as contained in this notice, the name of Robert M Supnik shall not be
used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from Robert M Supnik.
This memorandum documents the GRI-909 simulator.
1. Simulator Files
sim/ scp.h
sim_console.h
sim_defs.h
sim_fio.h
sim_rev.h
sim_sock.h
sim_timer.h
sim_tmxr.h
scp.c
sim_console.c
sim_fio.c
sim_sock.c
sim_timer.c
sim_tmxr.c
sim/gri/ lgp_defs.h
lgp_cpu.c
lgp_stddev.c
lgp_sys.c
2. LGP Features
The LGP is configured as follows:
device simulates
name(s)
CPU LGP-30 or LGP-21 CPU with 4096 words of memory
TTI Typewriter input (keyboard and reader)
TTO Typewriter output (printer and punch)
PTR high-speed paper tape reader
PTP high-speed paper tape punch
The LGP simulator implements the following unique stop conditions:
- LGP-30 only: arithmetic overflow
- LGP-21 only: reference to undefined I/O device.
The LOAD and DUMP commands are not implemented.
2.1 CPU
The CPU implements either the LGP-30 or the LGP-21:
SET CPU LGP30 set LGP-30
SET CPU LGP21 set LGP-21
The default is the LGP-30. Memory size is fixed at 4096 words.
The following commands implement various front panel functions:
D A value equivalent to the MANUAL INPUT button
SET CPU FILL{=value} equivalent to the FILL INSTRUCTION button;
if no value is given, fills IR from A;
otherwise, fills IR from the specified value
SET CPU EXEC{=value} equivalent to the EXECUTE button;
if no value is given, executes the instruction
in IR; otherwise, executes the instruction
specified by the value
SET CPU MANUAL equivalent to setting the MANUAL INPUT switch
on the Typewriter; Typewriter input is taken
from the keyboard
SET CPU TAPE equivalent to clearing the MANUAL INPUT switch
on the Typewriter; TYpewriter input is taken
from the Typewriter paper tape reader
The following commands control the display of information:
SET CPU LGPHEX numeric displays use LGP hexadecimal encoding
SET CPU STANDARD numeric displays use standard hexadecimal
SET CPU TRACK symbolic addresses are ttss, where tt = track
(0-63) and ss = sector (0-63)
SET CPU NORMAL symbolic addresses are normal linear addresses,
from 0 to 4095.
The defaults are STANDARD hex and TRACK addresses.
The LGP-30 implements the following additional commands:
SET CPU 4B sets the CPU to 4-bit input mode
SET CPU 6B sets the CPU to 6-bit input mode
SET CPU INPUT=TTI sets the CPU to read from the Typewriter
SET CPU INPUT=PTR sets the CPU to read from the high-speed reader
SET CPU OUTPUT=TTO sets the CPU to output to the Typewriter
SET CPU OUTPUT=PTP sets the CPU to output to the high-speed punch
The defaults are TAPE input, 4B input mode, input and output assigned to the
Typewriter.
CPU registers include the visible state of the processor as well as the
control registers for the interrupt system.
name size comments
PC 12 counter
A 32 accumulator
IR 32 instruction register
OVF 1 overflow flag (LGP-21 only)
TSW 1 transfer switch
BP32 1 breakpoint 32 switch
BP16 1 breakpoint 16 switch
BP8 1 breakpoint 8 switch
BP4 1 breakpoint 4 switch
INPST 1 input pending flag
INPDN 1 input done flag
OUTST 1 output pending flag
OUTDN 1 output done flag
WRU 8 interrupt character
2.2 Typewriter Input (TTI)
The Typewriter input consists of two units: the keyboard (unit 0) and
the paper-tape reader (unit 1). The keyboard is permanently associated
with the console window. The paper-tape reader can be attached to a
disk file. The RPOS register specifies the number of the next data item
to be read. Thus, by changing RPOS, the user can backspace or advance
the reader.
The Typewriter input has the following options:
SET TTI1 ASCII default tape file format is ASCII-encoded
Flex
SET TTI1 FLEX default tape file format is transposed Flex
SET TTI1 CSTOP reader recognizes conditional stop
SET TTI1 NOCSTOP reader ignores conditional stop
SET TTI RSTART start the reader; equivalent to the
START READER lever
SET TTI RSTOP stop the reader; equivalent to the
STOP READER lever
SET TTI START send START signal to the CPU; equivalent
to the START COMPUTE lever
Transposed Flex has the tape channels in this order: 6-1-2-3-4-5.
The ATTACH command recognizes two switches:
ATT -A TTI1 file file format is ASCII-encoded Flex
ATT -F TTI1 file file format is transposed Flex
The Typewriter input implements these registers:
name size comments
BUF 6 data buffer
RDY 1 data ready flag
KPOS 32 count of keyboard characters
RPOS 32 position in the reader input file
TIME 24 time between keyboard polls/reader characters
STOP_IOE 1 stop on I/O error
Error handling for the Typewriter paper-tape reader is as follows:
error STOP_IOE processed as
not attached 1 report error and stop
0 out of tape
end of file 1 report error and stop
0 out of tape
OS I/O error x report error and stop
2.3 Typewriter Output (TTO)
The Typewriter output consists of two units: the printer (unit 0) and
the paper-tape punch (unit 1). The printer is permanently associated
with the console window. The paper-tape punch can be attached to a
disk file. The PPOS register specifies the number of the next data item
to be written. Thus, by changing PPOS, the user can backspace or advance
the reader.
The Typewriter output has the following options:
SET TTO1 ASCII default tape file format is ASCII-encoded
Flex
SET TTO1 FLEX default tape file format is transposed Flex
SET TTO1 FEED=n punch 'n' feed (0) characters
Transposed Flex has the tape channels in this order: 6-1-2-3-4-5. The
default is ASCII-encoded Flex.
The ATTACH command recognizes two switches:
ATT -A TTO1 file file format is ASCII-encoded Flex
ATT -F TTO1 file file format is transposed Flex
The Typewriter output implements these registers:
name size comments
BUF 6 data buffer
UC 1 upper case flag
TPOS 32 count of output characters
PPOS 32 position in the punch output file
TIME 24 time from I/O initiation to completion
STOP_IOE 1 stop on I/O error
Error handling is as follows:
error STOP_IOE processed as
not attached 1 report error and stop
0 out of tape
OS I/O error x report error and stop
2.4 High Speed Paper-Tape Reader (PTR)
The paper tape reader (PTR) reads data from or a disk file. The POS
register specifies the number of the next data item to be read.
Thus, by changing POS, the user can backspace or advance the reader.
The paper-tape reader has the following options:
SET PTR ASCII default tape file format is ASCII-encoded
Flex
SET PTR FLEX default tape file format is transposed Flex
Transposed Flex has the tape channels in this order: 6-1-2-3-4-5. The
default is ASCII-encoded Flex.
The ATTACH command recognizes two switches:
ATT -A PTR file file format is ASCII-encoded Flex
ATT -F PTR file file format is transposed Flex
The paper tape reader implements these registers:
name size comments
BUF t last data item processed
RDY 1 data ready flag
POS 32 position in the input file
TIME 24 time from I/O initiation to completion
STOP_IOE 1 stop on I/O error
Error handling is as follows:
error STOP_IOE processed as
not attached 1 report error and stop
0 out of tape
end of file 1 report error and stop
0 out of tape
OS I/O error x report error and stop
2.5 High Speed Paper-Tape Punch (PTP)
The paper tape punch (PTP) writes data to a disk file. The POS
register specifies the number of the next data item to be written.
Thus, by changing POS, the user can backspace or advance the punch.
The paper tape punch has the following options:
SET PTP ASCII default tape file format is ASCII-encoded
Flex
SET PTP FLEX default tape file format is transposed Flex
SET PTP FEED=n punch 'n' feed (0) characters
Transposed Flex has the tape channels in this order: 6-1-2-3-4-5. The
default is ASCII-encoded Flex.
The ATTACH command recognizes two switches:
ATT -A PTP file file format is ASCII-encoded Flex
ATT -F PTP file file format is transposed Flex
The paper tape punch implements these registers:
name size comments
BUF 6 last data item processed
POS 32 position in the output file
TIME 24 time from I/O initiation to completion
STOP_IOE 1 stop on I/O error
Error handling is as follows:
error STOP_IOE processed as
not attached 1 report error and stop
0 out of tape
OS I/O error x report error and stop
2.6 Symbolic Display and Input
The LGP simulator implements symbolic display and input. Display is
controlled by command line switches:
-a display as character (tape files only)
-h display as standard hexadecimal
-l display as LGP hexadecimal
-m display instruction mnemonics
-n display addresses in normal format
(overrides SET CPU TRACK)
-t display addresses as track/sector
(overrides SET CPU NORMAL)
Input parsing is controlled by the first character typed in or by command
line switches:
' or -a Flex character
- or opcode instruction mnemonic
numeric hexadecimal number
LGP hexadecimal differs from standard hexadecimal in the characters used
for digits 10-15
digit standard hex LPG hex
10 A F
11 B G
12 C J
13 D K
14 E Q
15 F W
There is only instruction format:
{-}op address
'op' is always a single letter. A track/sector address (specified by
SET CPU TRACK or switch -t) is two decimal numbers between 0 and 63,
representing the track and sector. A linear address (specified by
SET CPU NORMAL or switch -n) is one decimal number between 0 and 4095.
For example:
sim> d -n 64 10640
sim> ex -mn 64
64: B 400
sim> ex -mt 100
0100: B 0616
2.7 Character Set
The LGP Typewriter was a Friden Flexowriter. Input was always upper case;
output could be either upper case or lower case. The following table provides
equivalences between LPG Typewriter coding and ASCII.
Typewriter Input LC output UC output
code (hex)
00 illegal illegal illegal
01 z or Z z Z
02 0 or ) 0 )
03 space space space
04 illegal lower case lower case
05 b or B b B
06 1 or L 1 L
07 - or _ 0 _
10 illegal upper case upper case
11 y or Y y Y
12 2 or * 2 *
13 + or = + =
14 illegal color shift color shift
15 r or R r R
16 3 or " 3 "
17 ; or : ; :
20 newline newline newline
21 i or I i I
22 4 or ^ 4 ^
23 / or ? / ?
24 illegal backspace backspace
25 d or D d D
26 5 or % 5 %
27 . or ] . ]
30 tab tab tab
31 n or N n N
32 6 or $ 6 $
33 , or [ , [
34 illegal illegal illegal
35 m or M m M
36 7 or ~ 7 ~
37 v or V v V
40 ' (cond stop) ' '
41 p or P p P
42 8 or # 8 #
43 o or O o O
44 illegal illegal illegal
45 e or E e E
46 9 or ( 9 (
47 x or X x X
50 illegal illegal illegal
51 u or U u U
52 f or F f F
53 illegal illegal illegal
54 illegal illegal illegal
55 t or T t T
56 g or G g G
57 illegal illegal illegal
60 illegal illegal illegal
61 h or H h H
62 j or J j J
63 illegal illegal illegal
64 illegal illegal illegal
65 c or C c C
66 k or K k K
67 illegal illegal illegal
70 illegal illegal illegal
71 a or A a A
72 q or Q q Q
73 illegal illegal illegal
74 illegal illegal illegal
75 s or S s S
76 w or W w W
77 illegal illegal illegal
Certain characters on the Flexowriter keyboard don't exist in ASCII.
The following table provides ASCII substitution characters for the unique
Flexowriter characters (this is compatible with the coding in the LGP30
paper tape archive):
Typewriter Flex ASCII
code
UC 12 delta ^
UC 1E pi ~
UC 22 sigma #
Certain Flexowriter codes have no character equivalent of any kind.
For paper-tape reader and punch files, these are encoded as #dd, where
dd is a decimal number between 0 and 63.

View file

@ -2,7 +2,7 @@
Modified from the original NOVA simulator by Robert Supnik. Modified from the original NOVA simulator by Robert Supnik.
Copyright (c) 1998-2005, Charles E Owen Copyright (c) 1998-2006, Charles E Owen
Portions Copyright (c) 1993-2002, Robert M Supnik Portions Copyright (c) 1993-2002, Robert M Supnik
Permission is hereby granted, free of charge, to any person obtaining a Permission is hereby granted, free of charge, to any person obtaining a
@ -28,6 +28,7 @@
cpu Eclipse central processor cpu Eclipse central processor
06-Feb-06 RMS Fixed bug in DIVS (found by Mark Hittinger)
22-Sep-05 RMS Fixed declarations (from Sterling Garwood) 22-Sep-05 RMS Fixed declarations (from Sterling Garwood)
25-Aug-05 RMS Fixed DIVS overflow cases 25-Aug-05 RMS Fixed DIVS overflow cases
29-Nov-03 CEO Corrected POPJ and Bit operations bugs 29-Nov-03 CEO Corrected POPJ and Bit operations bugs
@ -1664,7 +1665,7 @@ if ((IR & 0100017) == 0100010) { /* This pattern for all
} }
if (IR == 0157710) { /* DIVS: Signed Divide */ if (IR == 0157710) { /* DIVS: Signed Divide */
if ((AC[0] == 0) || if ((AC[0] == 0) ||
((AC[0] = 0100000) && (AC[1] == 0) && (AC[2] = 0177777))) ((AC[0] == 0100000) && (AC[1] == 0) && (AC[2] = 0177777)))
C = 0200000; C = 0200000;
else { else {
sAC2 = AC[2]; sAC2 = AC[2];

View file

@ -1,6 +1,6 @@
/* nova_cpu.c: NOVA CPU simulator /* nova_cpu.c: NOVA CPU simulator
Copyright (c) 1993-2005, Robert M. Supnik Copyright (c) 1993-2006, Robert M. Supnik
Permission is hereby granted, free of charge, to any person obtaining a Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"), copy of this software and associated documentation files (the "Software"),
@ -25,6 +25,7 @@
cpu Nova central processor cpu Nova central processor
06-Feb-06 RMS Fixed bug in DIVS (found by Mark Hittinger)
22-Sep-05 RMS Fixed declarations (from Sterling Garwood) 22-Sep-05 RMS Fixed declarations (from Sterling Garwood)
25-Aug-05 RMS Fixed DIVS case 2^31 / - 1 25-Aug-05 RMS Fixed DIVS case 2^31 / - 1
14-Jan-04 RMS Fixed device enable/disable support (found by Bruce Ray) 14-Jan-04 RMS Fixed device enable/disable support (found by Bruce Ray)
@ -743,7 +744,7 @@ while (reason == 0) { /* loop until halted */
} }
if (pulse == iopN) { /* divs */ if (pulse == iopN) { /* divs */
if ((AC[2] == 0) || /* overflow? */ if ((AC[2] == 0) || /* overflow? */
((AC[0] = 0100000) && (AC[1] == 0) && (AC[2] == 0177777))) ((AC[0] == 0100000) && (AC[1] == 0) && (AC[2] == 0177777)))
C = CBIT; C = CBIT;
else { else {
mddata = (SEXT (AC[0]) << 16) | AC[1]; mddata = (SEXT (AC[0]) << 16) | AC[1];

View file

@ -1,682 +0,0 @@
To: Users
From: Bob Supnik
Subj: Nova Simulator Usage
Date: 15-Nov-2004
COPYRIGHT NOTICE
The following copyright notice applies to both the SIMH source and binary:
Original code published in 1993-2005, written by Robert M Supnik
Copyright (c) 1993-2005, Robert M Supnik
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Except as contained in this notice, the name of Robert M Supnik shall not be
used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from Robert M Supnik.
This memorandum documents the Nova simulator.
1. Simulator Files
sim/ scp.h
sim_console.h
sim_defs.h
sim_fio.h
sim_rev.h
sim_sock.h
sim_tape.h
sim_timer.h
sim_tmxr.h
scp.c
sim_console.c
sim_fio.c
sim_sock.c
sim_tape.c
sim_timer.c
sim_tmxr.c
sim/nova/ nova_defs.h
nova_cpu.c
nova_clk.c
nova_dkp.c
nova_dsk.c
nova_lp.c
nova_mta.c
nova_plt.c
nova_qty.c
nova_sys.c
nova_tt.c
nova_tt1.c
2. Nova Features
The Nova simulator is configured as follows:
device simulates
name(s)
CPU Nova, Nova 3, or Nova 4 CPU with 32KW of memory
- hardware multiply/divide
PTR,PTP paper tape reader/punch
TTI,TTO console terminal
TTI1,TTO1 second terminal
LPT line printer
PLT plotter
CLK real-time clock
DK head-per-track disk controller
DP moving head disk controller with four drives
MT magnetic tape controller with eight drives
QTY 4060 multiplexor with up to 64 lines
ALM 4255 multiplexor with up to 64 lines
The Nova simulator implements these unique stop conditions:
- reference to undefined I/O device, and STOP_DEV is set
- more than INDMAX indirect addresses are detected during
an interrupt
- more than INDMAX indirect addresses are detected during
memory reference address decoding
Note that indirect address loop detection does not exist on unmapped
Novas. Some DG diagnostics test thousands of levels of indirect
addressing. INDMAX may have to be set to 32,000 to get diagnostics
to run properly.
The Nova loader supports standard binary format tapes. The DUMP command
is not implemented.
Most devices can be disabled or enabled, by the commands:
SET <dev> DISABLED
SET <dev> ENABLED
All devices are enabled by default.
2.1 CPU
The only CPU options are the presence of the optional instructions
and the size of main memory.
SET CPU MDV enable multiply/divide
SET CPU NOVA3 enable Nova3 instructions
SET CPU NOVA4 enable Nova4 instructions
SET CPU NONE disable all optional instructions
SET CPU 4K set memory size = 4K
SET CPU 8K set memory size = 8K
SET CPU 12K set memory size = 12K
SET CPU 16K set memory size = 16K
SET CPU 20K set memory size = 20K
SET CPU 24K set memory size = 24K
SET CPU 28K set memory size = 28K
SET CPU 32K set memory size = 32K
(MDV = unsigned multiply/divide instructions)
(Nova 3 = unsigned multiply/divide, stack, trap instructions)
(Nova 4 = unsigned and signed multiply/divide, stack, byte, trap instructions)
If memory size is being reduced, and the memory being truncated contains
non-zero data, the simulator asks for confirmation. Data in the truncated
portion of memory is lost. Initial memory size is 32K.
The CPU supports the boot command. BOOT CPU simulates the Nova hardware
APL (automatic program load) feature. The switch register (SR) bits 12:17
must contain the device code of the device to be booted. If the device is
a "high-speed" (channel) device, SR bit 0 should also be set.
CPU registers include the visible state of the processor as well as the
control registers for the interrupt system.
name size comments
PC 15 program counter
AC0..AC3 16 accumulators 0..3
C 1 carry
SR 16 front panel switches
PI 16 priority interrupt mask
ION 1 interrupt enable
ION_DELAY 1 interrupt enable delay for ION
PWR 1 power fail interrupt
INT 15 interrupt pending flags
BUSY 15 device busy flags
DONE 15 device done flags
DISABLE 15 device interrupt disable flags
STOP_DEV 1 stop on undefined IOT
INDMAX 15 maximum number of nested indirects
PCQ[0:63] 15 PC prior to last JMP, JMS, or interrupt;
most recent PC change first
WRU 8 interrupt character
2.2 Programmed I/O Devices
2.2.1 Paper Tape Reader (PTR)
The paper tape reader (PTR) reads data from a disk file. The POS
register specifies the number of the next data item to be read. Thus,
by changing POS, the user can backspace or advance the reader.
The paper tape reader implements these registers:
name size comments
BUF 8 last data item processed
BUSY 1 device busy flag
DONE 1 device done flag
DISABLE 1 interrupt disable flag
INT 1 interrupt pending flag
POS 32 position in the input file
TIME 24 time from I/O initiation to interrupt
STOP_IOE 1 stop on I/O error
Error handling is as follows:
error STOP_IOE processed as
not attached 1 report error and stop
0 out of tape or paper
end of file 1 report error and stop
0 out of tape or paper
OS I/O error x report error and stop
2.2.2 Paper Tape Punch (PTP)
The paper tape punch (PTP) writes data to a disk file. The POS
register specifies the number of the next data item to be written.
Thus, by changing POS, the user can backspace or advance the punch.
The paper tape punch implements these registers:
name size comments
BUF 8 last data item processed
BUSY 1 device busy flag
DONE 1 device done flag
DISABLE 1 interrupt disable flag
INT 1 interrupt pending flag
POS 32 position in the output file
TIME 24 time from I/O initiation to interrupt
STOP_IOE 1 stop on I/O error
Error handling is as follows:
error STOP_IOE processed as
not attached 1 report error and stop
0 out of tape or paper
OS I/O error x report error and stop
2.2.3 Terminal Input (TTI)
The terminal input polls the console keyboard for input. Terminal
input options include the ability to set ANSI mode or limited Dasher
compatibility mode:
SET TTI ANSI normal mode
SET TTI DASHER Dasher mode
Setting either TTI or TTO changes both devices. In Dasher mode, carriage
return is changed to newline on input, and ^X is changed to backspace.
The terminal input implements these registers:
name size comments
BUF 8 last data item processed
BUSY 1 device busy flag
DONE 1 device done flag
DISABLE 1 interrupt disable flag
INT 1 interrupt pending flag
POS 32 number of characters input
TIME 24 keyboard polling interval
2.2.4 Terminal Output (TTO)
The terminal output writes to the simulator console window. Terminal
output options include the the ability to set ANSI mode or limited
Dasher compatibility mode:
SET TTO ANSI normal mode
SET TTO DASHER Dasher mode
Setting either TTI or TTO changes both devices. In Dasher mode, carriage
return is changed to newline on input, and ^X is changed to backspace.
The terminal output implements these registers:
name size comments
BUF 8 last data item processed
BUSY 1 device busy flag
DONE 1 device done flag
DISABLE 1 interrupt disable flag
INT 1 interrupt pending flag
POS 32 number of characters output
TIME 24 time from I/O initiation to interrupt
2.2.5 Line Printer (LPT)
The line printer (LPT) writes data to a disk file. The POS register
specifies the number of the next data item to be written. Thus,
by changing POS, the user can backspace or advance the printer.
The line printer implements these registers:
name size comments
BUF 8 last data item processed
BUSY 1 device busy flag
DONE 1 device done flag
DISABLE 1 interrupt disable flag
INT 1 interrupt pending flag
POS 32 position in the output file
TIME 24 time from I/O initiation to interrupt
STOP_IOE 1 stop on I/O error
Error handling is as follows:
error STOP_IOE processed as
not attached 1 report error and stop
0 out of paper
OS I/O error x report error and stop
2.2.6 Real-Time Clock (CLK)
The real-time clock (CLK) line frequency can be adjusted as follows:
SET CLK 60HZ set line frequency to 60Hz
SET CLK 50HZ set line frequency to 50Hz
The default is 60Hz.
The clock implements these registers:
name size comments
SELECT 2 selected clock interval
BUSY 1 device busy flag
DONE 1 device done flag
DISABLE 1 interrupt disable flag
INT 1 interrupt pending flag
TIME0 24 clock frequency, select = 0
TIME1 24 clock frequency, select = 1
TIME2 24 clock frequency, select = 2
TIME3 24 clock frequency, select = 3
The real-time clock autocalibrates; the clock interval is adjusted up
or down so that the clock tracks actual elapsed time.
2.2.7 Plotter (PTP)
The plotter (PLT) writes data to a disk file. The POS register
specifies the number of the next data item to be written. Thus,
by changing POS, the user can backspace or advance the plotter.
The plotter implements these registers:
name size comments
BUF 8 last data item processed
BUSY 1 device busy flag
DONE 1 device done flag
DISABLE 1 interrupt disable flag
INT 1 interrupt pending flag
POS 32 position in the output file
TIME 24 time from I/O initiation to interrupt
STOP_IOE 1 stop on I/O error
Error handling is as follows:
error STOP_IOE processed as
not attached 1 report error and stop
0 out of tape or paper
OS I/O error x report error and stop
2.2.8 Second Terminal (TTI1, TTO1)
The second terminal consists of two independent devices, TTI1 and TTO1.
The additional terminal performs input and output through a Telnet session
connecting into a user-specified port. The ATTACH command specifies the
port to be used:
ATTACH TTI1 <port> set up listening port
where port is a decimal number between 1 and 65535 that is not being used
for other TCP/IP activities.
Once TTI1 is attached and the simulator is running, the terminal listens
for a connection on the specified port. It assumes that the incoming
connection is a Telnet connection. The connection remain opens until
disconnected by the Telnet client, or by a DETACH TTI1 command.
The second terminal has two options, recognized on both devices, for
setting limited Dasher-compatibility mode or ANSI mode:
SET TTI1 ANSI normal mode
SET TTI1 DASHER Dasher mode
SET TTO1 ANSI normal mode
SET TTO1 DASHER Dasher mode
Setting either TTI1 or TTO1 changes both devices. In Dasher mode, carriage
return is changed to newline on input, and ^X is changed to backspace.
TTO1 supports output logging. The SET TTO1 LOG command enables logging:
SET TTO1 LOG=filename log output to filename
The SET TTO1 NOLOG command disables logging and closes the open log
file, if any.
The SHOW TTI1 CONNECTIONS command displays the current connection to TTI1.
The SHOW TTI1 STATISTICS command displays statistics for the current connection.
The SET TTI1 DISCONNECT{=0} disconnects the current connection.
The second terminal input implements these registers:
name size comments
BUF 8 last data item processed
BUSY 1 device busy flag
DONE 1 device done flag
DISABLE 1 interrupt disable flag
INT 1 interrupt pending flag
TIME 24 keyboard polling interval
The second terminal output implements these registers:
name size comments
BUF 8 last data item processed
BUSY 1 device busy flag
DONE 1 device done flag
DISABLE 1 interrupt disable flag
INT 1 interrupt pending flag
TIME 24 time from I/O initiation to interrupt
2.2.8 Asynchronous Multiplexors (QTY, ALM)
The QTY and ALM are terminal multiplexors with up to 64 lines. Either
the QTY or ALM can be enabled, but not both; the ALM is enabled by
default. The number of lines can be changed with the command
SET {QTY|ALM} LINES=n set line count to n
The line count maximum is 64.
The QTY and ALM support 8-bit input and output of characters. 8-bit I/O
may be incompatible with certain operating systems; 7-bit is the default.
The command
SET {QTY|ALM} 8B
enables 8-bit input and output.
The terminal lines perform input and output through Telnet sessions
connected to a user-specified port. The ATTACH command specifies
the port to be used:
ATTACH {-am} {QTY|ALM} <port> set up listening port
where port is a decimal number between 1 and 65535 that is not being used
for other TCP/IP activities. For the ALM multiplexor, the optional switch
-m turns on the multiplexor modem controls; the optional switch -a turns on
active disconnects (disconnect session if computer clears Data Terminal Ready).
The QTY multiplexor does not support modem control. Without modem control,
the multiplexor behaves as though terminals were directly connected;
disconnecting the Telnet session does not cause any operating system-
visible change in line status.
Once the multiplexor is attached and the simulator is running, it will listen
for connections on the specified port. It assumes that the incoming
connections are Telnet connections. The connection remains open until
disconnected by the simulated program, the Telnet client, a SET {QTY|ALM}
DISCONNECT command, or a DETACH {QTY|ALM} command.
The SHOW {QTY|ALM} CONNECTIONS command displays the current connections to
the multiplexor. The SHOW {QTY|ALM} STATISTICS command displays statistics
for active connections. The SET {QTY|ALM| DISCONNECT=linenumber disconnects
the specified line.
The QTY/ALM implement these registers:
name size comments
BUF 8 character buffer
BUSY 1 device busy flag
DONE 1 device done flag
DISABLE 1 device disable flag
INT 1 interrupt pending flag
MDMCTL 1 modem control flag
AUTODS 1 autodisconnect flag
POLLS 32 number of service polls
STOP_IOE 1 stop on I/O error
The multiplexors do not support save and restore. All open connections are
lost when the simulator shuts down or the multiplexor is detached.
2.3 Fixed Head Disk (DK)
Fixed head disk 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
from the attached file:
SET RF 1P one platter (256K)
SET RF 2P two platters (512K)
SET RF 3P three platters (768K)
SET RF 4P four platters (1024K)
SET RF 5P five platters (1280K)
SET RF 6P six platters (1536K)
SET RF 7P seven platters (1792K)
SET RF 8P eight platters (2048K)
SET RF AUTOSIZE autosized on attach
The default is 1P (minimum size).
The fixed head disk controller implements these registers:
name size comments
STAT 16 status
DA 16 disk address
MA 16 memory address
BUSY 1 device busy flag
DONE 1 device done flag
DISABLE 1 device disable flag
INT 1 interrupt pending flag
WLK 8 write lock switches
TIME 24 rotational delay, per sector
STOP_IOE 1 stop on I/O error
The fixed head disk controller supports the BOOT command.
Error handling is as follows:
error STOP_IOE processed as
not attached 1 report error and stop
0 disk not ready
Fixed head disk data files are buffered in memory; therefore, end of file
and OS I/O errors cannot occur.
2.4 Moving Head Disk (DP)
Moving head disk options include the ability to make units write enabled or
write locked, and to select the type of drive:
SET DPn LOCKED set unit n write locked
SET DPn WRITEENABLED set unit n write enabled
SET DPn FLOPPY set unit n to floppy disk
SET DPn D31 set unit n to Diablo 31
SET DPn D44 set unit n to Diablo 44
SET DPn C111 set unit n to Century 111
SET DPn C114 set unit n to Century 114
SET DPn 6225 set unit n to 6225
SET DPn 6099 set unit n to 6099
SET DPn 6227 set unit n to 6227
SET DPn 6070 set unit n to 6070
SET DPn 6103 set unit n to 6103
SET DPn 4231 set unit n to 4231
Units can also be set ENABLED or DISABLED. The moving head disk controller
supports the BOOT command.
All drives have 256 16b words per sector. The other disk parameters are:
drive cylinders surfaces sectors size (MW) DG models
floppy 77 1 8 .158 6038
D31 203 2 12 1.247 4047, 4237, 4238
D44 408 4 12 5.014 4234, 6045
C111 203 10 6 3.118 4048
C114 203 20 12 12.472 4057, 2314
6225 245 2 20 2.508
6099 192 4 32 6.291
6227 245 6 20 7.526
6070 408 4 24 10.027
6103 192 8 32 12.583
4231 411 19 23 45.979
The moving head disk controller implements these registers:
name size comments
FCCY 16 flags, command, cylinder
USSC 16 unit, surface, sector, count
STAT 16 status
MA 16 memory address
BUSY 1 device busy flag
DONE 1 device done flag
DISABLE 1 interrupt disable flag
INT 1 interrupt pending flag
DIAG 1 diagnostic mode flag
MAP 2 map select
STIME 24 seek time, per cylinder
RTIME 24 rotational delay
Error handling is as follows:
error processed as
not attached disk not ready
end of file assume rest of disk is zero
OS I/O error report error and stop
2.5 Magnetic Tape (MT)
Magnetic tape options include the ability to make units write enabled or
or write locked.
SET MTn LOCKED set unit n write locked
SET MTn WRITEENABLED set unit n write enabled
Units can also be set ENABLED or DISABLED. The magnetic tape controller
supports the BOOT command.
The magnetic tape controller implements these registers:
name size comments
CU 16 command, unit
MA 16 memory address
WC 16 word count
STA1 16 status word 1
STA2 16 status word 2
EP 1 extended polling mode (not supported)
BUSY 1 device busy flag
DONE 1 device done flag
DISABLE 1 interrupt disable flag
INT 1 interrupt pending flag
STOP_IOE 1 stop on I/O error
CTIME 24 controller delay
RTIME 24 record delay
UST[0:7] 32 unit status, units 0-7
POS[0:7] 31 position, units 0-7
Error handling is as follows:
error processed as
not attached tape not ready
end of file bad tape
OS I/O error report error and stop
2.6 Symbolic Display and Input
The Nova simulator implements symbolic display and input. Display is
controlled by command line switches:
-a display as ASCII character
-c display as two character ASCII string
-m display instruction mnemonics
Input parsing is controlled by the first character typed in or by command
line switches:
' or -a ASCII character
" or -c two character ASCII string
alphabetic instruction mnemonic
numeric octal number
Instruction input uses standard Nova assembler syntax. There are three
instruction classes: memory reference, IOT, and operate.
Memory reference instructions have the format
memref {ac,}{@}address{,index}
LDA and STA require an initial register; ISZ, DSZ, JSR, and JMP do not.
The syntax for addresses and indices is as follows:
syntax mode displacement comments
0 <= n < 0400 0 n
{+/-}n >= 0400 1 {+/-}n - PC must be in range [-200, 177]
invalid on disk
.+/-n 1 {+/-}n must be in range [-200, 177]
{+/-}n,2 2 {+/-}n must be in range [-200, 177]
{+/-}n,3 3 {+/-}n must be in range [-200, 177]
IOT instructions have one of four formats
syntax example
iot HALT
iot reg INTA
iot device SKPDN
iot reg,device DOAS
Devices may be specified as mnemonics or as numbers in the range 0 - 077.
Operate instructions have the format
opcode{#} reg,reg{,skip}
In all Nova instructions, blanks may be substituted for commas as field
delimiters.

View file

@ -1,6 +1,6 @@
/* nova_dsk.c: 4019 fixed head disk simulator /* nova_dsk.c: 4019 fixed head disk simulator
Copyright (c) 1993-2005, Robert M. Supnik Copyright (c) 1993-2006, Robert M. Supnik
Permission is hereby granted, free of charge, to any person obtaining a Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"), copy of this software and associated documentation files (the "Software"),
@ -25,6 +25,7 @@
dsk fixed head disk dsk fixed head disk
15-May-06 RMS Fixed bug in autosize attach (reported by David Gesswein)
04-Jan-04 RMS Changed sim_fsize calling sequence 04-Jan-04 RMS Changed sim_fsize calling sequence
26-Jul-03 RMS Fixed bug in set size routine 26-Jul-03 RMS Fixed bug in set size routine
14-Mar-03 RMS Fixed variable capacity interaction with save/restore 14-Mar-03 RMS Fixed variable capacity interaction with save/restore
@ -296,17 +297,14 @@ t_stat dsk_attach (UNIT *uptr, char *cptr)
{ {
uint32 sz, p; uint32 sz, p;
uint32 ds_bytes = DSK_DKSIZE * sizeof (int16); uint32 ds_bytes = DSK_DKSIZE * sizeof (int16);
t_stat r;
r = attach_unit (uptr, cptr); if ((uptr->flags & UNIT_AUTO) && (sz = sim_fsize_name (cptr))) {
if (r != SCPE_OK) return r;
if ((uptr->flags & UNIT_AUTO) && (sz = sim_fsize (uptr->fileref))) {
p = (sz + ds_bytes - 1) / ds_bytes; p = (sz + ds_bytes - 1) / ds_bytes;
if (p >= DSK_NUMDK) p = DSK_NUMDK - 1; if (p >= DSK_NUMDK) p = DSK_NUMDK - 1;
uptr->flags = (uptr->flags & ~UNIT_PLAT) | (p << UNIT_V_PLAT); uptr->flags = (uptr->flags & ~UNIT_PLAT) | (p << UNIT_V_PLAT);
} }
uptr->capac = UNIT_GETP (uptr->flags) * DSK_DKSIZE; /* set capacity */ uptr->capac = UNIT_GETP (uptr->flags) * DSK_DKSIZE; /* set capacity */
return SCPE_OK; return attach_unit (uptr, cptr);
} }
/* Change disk size */ /* Change disk size */

View file

@ -1,572 +0,0 @@
To: Users
From: Bob Supnik
Subj: PDP-1 Simulator Usage
Date: 15-Nov-2004
COPYRIGHT NOTICE
The following copyright notice applies to both the SIMH source and binary:
Original code published in 1993-2005, written by Robert M Supnik
Copyright (c) 1993-2005, Robert M Supnik
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Except as contained in this notice, the name of Robert M Supnik shall not be
used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from Robert M Supnik.
This memorandum documents the PDP-1 simulator.
1. Simulator Files
sim/ scp.h
sim_console.h
sim_defs.h
sim_fio.h
sim_rev.h
sim_sock.h
sim_timer.h
sim_tmxr.h
scp.c
sim_console.c
sim_fio.c
sim_sock.c
sim_timer.c
sim_tmxr.c
sim/pdp1/ pdp1_defs.h
pdp1_cpu.c
pdp1_drm.c
pdp1_dt.c
pdp1_lp.c
pdp1_stddev.c
pdp1_sys.c
2. PDP-1 Features
The PDP-1 is configured as follows:
device simulates
name(s)
CPU PDP-1 CPU with up to 64KW of memory
PTR,PTP integral paper tape reader/punch
TTY console typewriter
LPT Type 62 line printer
DRM Type 24 serial drum
DRP Type 23 parallel drum
DT Type 550 Microtape (DECtape)
The PDP-1 simulator implements the following unique stop conditions:
- an unimplemented instruction is decoded, and register
STOP_INST is set
- more than IND_MAX indirect addresses are detected during
memory reference address decoding
- more than XCT_MAX nested executes are detected during
instruction execution
- I/O wait, and no I/O operations outstanding (i.e, no I/O
completion will ever occur)
- a simulated DECtape runs off the end of its reel
The PDP-1 loader supports RIM format tapes and BLK format tapes. If
the file to be loaded has an extension of .BIN, or switch -B is specified,
the file is assumed to be BLK format; otherwise, it defaults to RIM
format. LOAD takes an optional argument which specifies the starting
address of the field to be loaded:
LOAD lisp.rim -- load RIM format file lisp.rim
LOAD ddt.rim 70000 -- load RIM format file ddt.rim into
the field starting at 70000
LOAD -B macro.blk -- load BLK format file macro.blk
The DUMP command is not implemented.
2.1 CPU
The only CPU options are the presence of hardware multiply/divide and the
size of main memory.
SET CPU MDV enable multiply/divide
SET CPU NOMDV disable multiply/divide
SET CPU 4K set memory size = 4K
SET CPU 8K set memory size = 8K
SET CPU 12K set memory size = 12K
SET CPU 16K set memory size = 16K
SET CPU 20K set memory size = 20K
SET CPU 24K set memory size = 24K
SET CPU 28K set memory size = 28K
SET CPU 32K set memory size = 32K
SET CPU 48K set memory size = 48K
SET CPU 64K set memory size = 64K
If memory size is being reduced, and the memory being truncated contains
non-zero data, the simulator asks for confirmation. Data in the truncated
portion of memory is lost. Initial memory size is 64K.
CPU registers include the visible state of the processor as well as the
control registers for the interrupt system.
name size comments
PC 16 program counter
AC 18 accumulator
IO 18 IO register
OV 1 overflow flag
PF 6 program flags<1:6>
SS 6 sense switches<1:6>
TA 16 address switches
TW 18 test word (front panel switches)
EXTM 1 extend mode
IOSTA 18 IO status register
SBON 1 sequence break enable
SBRQ 1 sequence break request
SBIP 1 sequence break in progress
IOH 1 I/O halt in progress
IOS 1 I/O synchronizer (completion)
PCQ[0:63] 16 PC prior to last jump or interrupt;
most recent PC change first
STOP_INST 1 stop on undefined instruction
SBS_INIT 1 initial state of sequence break enable
EXTM_INIT 1 initial state of extend mode
XCT_MAX 8 maximum XCT chain
IND_MAX 8 maximum nested indirect addresses
WRU 8 interrupt character
The CPU can maintain a history of the most recently executed instructions.
This is controlled by the SET CPU HISTORY and SHOW CPU HISTORY commands:
SET CPU HISTORY clear history buffer
SET CPU HISTORY=0 disable history
SET CPU HISTORY=n enable history, length = n
SHOW CPU HISTORY print CPU history
SHOW CPU HISTORY=n print first n entries of CPU history
The maximum length for the history is 65536 entries.
2.2 Programmed I/O Devices
2.2.1 Paper Tape Reader (PTR)
The paper tape reader (PTR) reads data from or a disk file. The POS
register specifies the number of the next data item to be read. Thus,
by changing POS, the user can backspace or advance the reader.
The paper tape reader supports the BOOT command. BOOT PTR copies the
RIM loader into memory and starts it running. BOOT PTR loads into the
field selected by TA<0:3> (the high order four bits of the address
switches).
The paper tape reader implements these registers:
name size comments
BUF 8 last data item processed
DONE 1 device done flag
RPLS 1 return restart pulse flag
POS 32 position in the input file
TIME 24 time from I/O initiation to interrupt
STOP_IOE 1 stop on I/O error
Error handling is as follows:
error STOP_IOE processed as
not attached 1 report error and stop
0 out of tape
end of file 1 report error and stop
0 out of tape
OS I/O error x report error and stop
2.2.2 Paper Tape Punch (PTP)
The paper tape punch (PTP) writes data to a disk file. The POS
register specifies the number of the next data item to be written.
Thus, by changing POS, the user can backspace or advance the punch.
The paper tape punch implements these registers:
name size comments
BUF 8 last data item processed
DONE 1 device done flag
RPLS 1 return restart pulse flag
POS 32 position in the output file
TIME 24 time from I/O initiation to interrupt
STOP_IOE 1 stop on I/O error
Error handling is as follows:
error STOP_IOE processed as
not attached 1 report error and stop
0 out of tape
OS I/O error x report error and stop
2.2.3 Console Typewriter (TTY)
The Typewriter is a half-duplex electric typewriter (originally a
Friden Flexowriter, later a Sorobon-modified IBM B). It has only a
single buffer and a single carriage state but distinct input and
output done and interrupt flags. The typewriter input (TTY unit 0)
polls the console keyboard for input. The typewriter output (TTY
unit 1) writes to the simulator console window.
The typewriter implements these registers:
name size comments
BUF 6 typewriter buffer
UC 1 upper case/lower case state flag
RPLS 1 return restart pulse flag
KDONE 1 input ready flag
KPOS 32 number of characters input
KTIME 24 keyboard polling interval
TDONE 1 output done flag
TPOS 32 number of characters output
TTIME 24 time from I/O initiation to interrupt
2.2.4 Type 62 Line Printer (LPT)
The paper line printer (LPT) writes data to a disk file. The POS
register specifies the number of the next data item to be written.
Thus, by changing POS, the user can backspace or advance the printer.
The line printer can be disabled and enabled with the SET LPT DISABLED
and SET LPT ENABLED commands, respectively.
The line printer implements these registers:
name size comments
BUF 8 last data item processed
PNT 1 printing done flag
SPC 1 spacing done flag
RPLS 1 return restart pulse flag
BPTR 6 print buffer pointer
POS 32 position in the output file
TIME 24 time from I/O initiation to interrupt
STOP_IOE 1 stop on I/O error
LBUF[0:119] 8 line buffer
Error handling is as follows:
error STOP_IOE processed as
not attached 1 report error and stop
0 out of tape or paper
OS I/O error x report error and stop
2.3 Type 550/555 Microtape (DECtape) (DT)
The PDP-1 uses the Type 550 Microtape (later renamed DECtape), a programmed
I/O controller. PDP-1 DECtape format has 4 18b words in its block headers
and trailers.
DECtapes drives are numbered 1-8; in the simulator, drive 8 is unit 0.
DECtape options include the ability to make units write enabled or write
locked.
SET DTn WRITEENABLED set unit n write enabled
SET DTn LOCKED set unit n write locked
Units can also be set ENABLED or DISABLED.
The DECtape controller can be disabled and enabled with the SET DT DISABLED
and SET DT ENABLED commands, respectively.
The Type 550 supports PDP-8 format, PDP-11 format, and 18b format DECtape
images. ATTACH tries to determine the tape format from the DECtape image;
the user can force a particular format with switches:
-r PDP-8 format
-s PDP-11 format
-t 18b format
The DECtape controller is a data-only simulator; the timing and mark
track, and block header and trailer, are not stored. Thus, the WRITE
TIMING AND MARK TRACK function is not supported; the READ ALL function
always returns the hardware standard block header and trailer; and the
WRITE ALL function dumps non-data words into the bit bucket.
The DECtape controller implements these registers:
name size comments
DTSA 12 status register A
DTSB 12 status register B
DTDB 18 data buffer
DTF 1 DECtape flag
BEF 1 block end flag
ERF 1 error flag
LTIME 31 time between lines
DCTIME 31 time to decelerate to a full stop
SUBSTATE 2 read/write command substate
POS[0:7] 32 position, in lines, units 0-7
STATT[0:7] 18 unit state, units 0-7
STOP_OFFR 1 stop on off-reel error
It is critically important to maintain certain timing relationships
among the DECtape parameters, or the DECtape simulator will fail to
operate correctly.
- LTIME must be at least 6
- DCTIME needs to be at least 100 times LTIME
Acceleration time is set to 75% of deceleration time.
2.4 Drums
The PDP-1 supported two drums: the Type 23 parallel drum (DRP) and
the Type 24 serial drum (DRM). Both use device addresses 061-064;
accordingly, only one can be enabled at a time. By default, the
Type 24 serial drum is enabled, and the Type 23 parallel drum is
disabled.
2.4.1 Type 24 Serial Drum (DRM)
The serial drum (DRM) implements these registers:
name size comments
DA 9 drum address (sector number)
MA 16 current memory address
DONE 1 device done flag
ERR 1 error flag
WLK 32 write lock switches
TIME 24 rotational latency, per word
STOP_IOE 1 stop on I/O error
Error handling is as follows:
error STOP_IOE processed as
not attached 1 report error and stop
0 disk not ready
Drum data files are buffered in memory; therefore, end of file and OS
I/O errors cannot occur.
2.4.2 Type 23 Parallel Drum (DRP)
The parallel drum (DRP) implements these registers:
name size comments
TA 12 track address
RDF 5 read field
RDE 1 read enable flag
WRF 5 write field
WRF 1 write enable flag
MA 16 current memory address
WC 12 word count
BUSY 1 device busy flag
ERR 1 error flag
TIME 24 rotational latency, per word
STOP_IOE 1 stop on I/O error
Error handling is as follows:
error STOP_IOE processed as
not attached 1 report error and stop
0 disk not ready
Drum data files are buffered in memory; therefore, end of file and OS
I/O errors cannot occur.
2.5 Symbolic Display and Input
The PDP-1 simulator implements symbolic display and input. Display is
controlled by command line switches:
-a display as ASCII character
-c display as FIODEC character string
-m display instruction mnemonics
Input parsing is controlled by the first character typed in or by command
line switches:
' or -a ASCII character
" or -c three character FIODEC string
alphabetic instruction mnemonic
numeric octal number
Instruction input uses modified PDP-1 assembler syntax. There are six
instruction classes: memory reference, shift, skip, operate, IOT, and
LAW.
Memory reference instructions have the format
memref {I} address
where I signifies indirect reference. The address is an octal number in
the range 0 - 0177777.
Shift instructions have the format
shift shift_count
The shift count is an octal number in the range 0-9.
Skip instructions consist of single mnemonics, eg, SZA, SZS4. Skip
instructions may be or'd together
skip skip skip...
The sense of a skip can be inverted by including the mnemonic I.
Operate instructions consist of single mnemonics, eg, CLA, CLI. Operate
instructions may be or'd together
opr opr opr...
IOT instructions consist of single mnemonics, eg, TYI, TYO. IOT
instructions may include an octal numeric modifier or the modifier I:
iot modifier
The simulator does not check the legality of skip, operate, or IOT
combinations.
Finally, the LAW instruction has the format
LAW {I} immediate
where immediate is in the range 0 to 07777.
2.6 Character Sets
The PDP-1's first console was a Frieden Flexowriter; its character encoding
was known as FIODEC. The PDP-1's line printer used a modified Hollerith
character set. The following table provides equivalences between ASCII
characters and the PDP-1's I/O devices. In the console table, UC stands
for upper case.
PDP-1 PDP-1
ASCII console line printer
000 - 007 none none
bs 075 none
tab 036 none
012 - 014 none none
cr 077 none
016 - 037 none none
space 000 000
! {OR} UC+005 none
" UC+001 none
# {IMPLIES} UC+004 none
$ none none
% none none
& {AND} UC+006 none
' UC+002 none
( 057 057
) 055 055
* {TIMES} UC+073 072
+ UC+054 074
, 033 033
- 054 054
. 073 073
/ 021 021
0 020 020
1 001 001
2 002 002
3 003 003
4 004 004
5 005 005
6 006 006
7 007 007
8 010 010
9 011 011
: none none
; none none
< UC+007 034
= UC+033 053
> UC+010 034
? UC+021 037
@ {MID DOT} 040 {MID DOT} 040
A UC+061 061
B UC+062 062
C UC+063 063
D UC+064 064
E UC+065 065
F UC+066 066
G UC+067 067
H UC+070 070
I UC+071 071
J UC+041 041
K UC+042 042
L UC+043 043
M UC+044 044
N UC+045 045
O UC+046 046
P UC+047 047
Q UC+050 050
R UC+051 051
S UC+022 022
T UC+023 023
U UC+024 024
V UC+025 025
W UC+026 026
X UC+027 027
Y UC+030 030
Z UC+031 031
[ UC+057 none
\ {OVERLINE} 056 {OVERLINE} 056
] UC+055 none
^ {UP ARROW} UC+011 {UP ARROW} 035
_ UC+040 UC+040
` {RT ARROW} UC+020 036
a 061 none
b 062 none
c 063 none
d 064 none
e 065 none
f 066 none
g 067 none
h 070 none
i 071 none
j 041 none
k 042 none
l 043 none
m 044 none
n 045 none
o 046 none
p 047 none
q 050 none
r 051 none
s 022 none
t 023 none
u 024 none
v 025 none
w 026 none
x 027 none
y 030 none
z 031 none
{ none none
| UC+056 076
} none none
~ UC+003 013
del 075 none

View file

@ -1,660 +0,0 @@
To: Users
From: Bob Supnik
Subj: PDP-10 Simulator Usage
Date: 01-Dec-2005
COPYRIGHT NOTICE
The following copyright notice applies to both the SIMH source and binary:
Original code published in 1993-2005, written by Robert M Supnik
Copyright (c) 1993-2005, Robert M Supnik
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Except as contained in this notice, the name of Robert M Supnik shall not be
used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from Robert M Supnik.
This memorandum documents the PDP-10 simulator.
1. Simulator Files
To compile the PDP-10, you must define VM_PDP10 and USE_INT64 as part of the
compilation command line.
sim/ scp.h
sim_console.h
sim_defs.h
sim_ether.h
sim_fio.h
sim_rev.h
sim_sock.h
sim_tape.h
sim_timer.h
sim_tmxr.h
scp.c
sim_console.c
sim_ether.c
sim_fio.c
sim_sock.c
sim_tape.c
sim_timer.c
sim_tmxr.c
sim/pdp10/ pdp10_defs.h
pdp10_cpu.c
pdp10_fe.c
pdp10_ksio.c
pdp10_lp20.c
pdp10_mdfp.c
pdp10_pag.c
pdp10_rp.c
pdp10_sys.c
pdp10_tu.c
pdp10_xtnd.c
sim/pdp11/ pdp11_dz.c
pdp11_pt.c
pdp11_ry.c
pdp11_xu.c
2. PDP-10 Features
The PDP-10 simulator is configured as follows:
device simulates
name(s)
CPU KS10 CPU with 1MW of memory
PAG paging unit (translation maps)
UBA Unibus adapters (translation maps)
FE console
TIM timer
PTR,PTP PC11 paper tape reader/punch
RY RX211/RX02 floppy disk and two drives
DZ DZ11 8-line terminal multiplexor (up to 4)
LP20 LP20 line printer
RP RH11/RP04/RP05/RP06/RP07/RM03/RM05/RM80 controller with
eight drives
TU RH11/TM02/TU45 controller with eight drives
XU DEUNA/DELUA Ethernet controller
The PTR, PTP, and RX211 are initially set DISABLED. The DZ11 and LP20 can
also be set DISABLED. Some devices support the SET ADDRESS command, which
allows the I/O page address of the device to be changed, and the SET VECTOR
command, which allows the vector of the device to be changed. All devices
support the SHOW ADDRESS and SHOW VECTOR commands, which display the device
address and vector, respectively.
The PDP-10 simulator implements several unique stop condition:
- illegal instruction (000) in kernel mode
- indirect addressing nesting exceeds limit
- execute chaining exceeds limit
- page fail or other error in interrupt sequence
- illegal instruction in interrupt sequence
- invalid vector pointer in interrupt sequence
- invalid Unibus adapter number
- non-existent exec or user page table address
The PDP-10 loader supports RIM10B format paper tapes, SAV binary files, and
EXE binary files. LOAD switches -r, -s, -e specify RIM10, SAV, EXE format,
respectively. If no switch is specified, the LOAD command checks the file
extension; .RIM, .SAV, .EXE specify RIM10, SAV, EXE format, respectively.
If no switch is specified, and no extension matches, the LOAD command checks
the file format to try to determine the file type.
2.1 CPU
The CPU options allow the user to specify standard microcode, standard
microcode with a bug fix for a boostrap problem in TOPS-20 V4.1, or ITS
microcode:
SET CPU STANDARD Standard microcode
SET CPU TOPS20V41 Standard microcode with TOPS-20 V4.1 bug fix
SET CPU ITS ITS compatible microcode
The CPU implements a SHOW command to display the I/O space address map:
SHOW CPU IOSPACE show I/O space address map
CPU registers include the visible state of the processor as well as the
control registers for the interrupt system.
name size comments
PC 18 program counter
FLAGS 18 processor flags (<13:17> unused)
AC0..AC17 36 accumulators
IR 36 instruction register
EBR 18 executive base register
PGON 1 paging enabled flag
T20P 1 TOPS-20 paging
UBR 18 user base register
CURAC 3 current AC block
PRVAC 3 previous AC block
SPT 36 shared pointer table
CST 36 core status table
PUR 36 process update register
CSTM 36 CST mask
HSB 18 halt status block address
DBR1 18 descriptor base register 1 (ITS)
DBR2 18 descriptor base register 2 (ITS)
DBR3 18 descriptor base register 3 (ITS)
DBR4 18 descriptor base register 4 (ITS)
PIENB 7 PI levels enabled
PIACT 7 PI levels active
PIPRQ 7 PI levels with program requests
PIIOQ 7 PI levels with IO requests
PIAPR 7 PI levels with APR requests
APRENB 8 APR flags enabled
APRFLG 8 APR flags active
APRLVL 3 PI level for APR interrupt
IND_MAX 8 indirect address nesting limit
XCT_MAX 8 execute chaining limit
PCQ[0:63] 18 PC prior to last jump or interrupt;
most recent PC change first
WRU 8 interrupt character
REG[0:127] 36 fast memory blocks
The CPU can maintain a history of the most recently executed instructions.
This is controlled by the SET CPU HISTORY and SHOW CPU HISTORY commands:
SET CPU HISTORY clear history buffer
SET CPU HISTORY=0 disable history
SET CPU HISTORY=n enable history, length = n
SHOW CPU HISTORY print CPU history
SHOW CPU HISTORY=n print first n entries of CPU history
The maximum length for the history is 65536 entries.
2.2 Pager
The pager contains the page maps for executive and user mode. The
executive page map is the memory space for unit 0, the user page map the
memory space for unit 1. A page map entry is 32 bits wide and has the
following format:
bit content
--- -------
31 page is writeable
30 entry is valid
29:19 mbz
18:9 physical page base address
8:0 mbz
The pager has no registers.
2.3 Unibus Adapters
The Unibus adapters link the system I/O devices to the CPU. Unibus
adapter 1 (UBA1) is unit 0, and Unibus adapter 3 is unit 1. The
adapter's Unibus map is the memory space of the corresponding unit.
The Unibus adapter has the following registers:
name size comments
INTREQ 32 interrupt requests
UB1CS 16 Unibus adapter 1 control/status
UB3CS 16 Unibus adapter 3 control/status
2.4 Front End (FE)
The front end is the system console. The keyboard input is unit 0,
the console output is unit 1. It supports one option:
SET FE STOP halts the PDP-10 operating system
The front end has the following registers:
name size comments
IBUF 8 input buffer
ICOUNT 32 count of input characters
ITIME 24 keyboard polling interval
OBUF 8 output buffer
OCOUNT 32 count of output characters
OTIME 24 console output response time
2.5 Timer (TIM)
The timer (TIM) implements the system timer, the interval timer, and
the time of day clock used to get the date and time at system startup.
Because most PDP-10 software is not Y2K compliant, the timer implements
one option:
SET TIM NOY2K software not Y2K compliant, limit time
of day clock to 1999 (default)
SET TIM Y2K software is Y2K compliant
The timer has the following registers:
name size comments
TIMBASE 59 time base (double precision)
TTG 36 time to go (remaining time) for interval
PERIOD 36 reset value for interval
QUANT 36 quantum timer (ITS only)
TIME 24 tick delay
DIAG 1 use fixed tick delay instead of autocalibration
Unless the DIAG flag is set, the timer autocalibrates; the tick delay
is adjusted up or down so that the time base tracks actual elapsed time.
This may cause time-dependent diagnostics to report errors.
2.6 PC11 Paper Tape Reader (PTR)
The paper tape reader (PTR) reads data from a disk file. The POS
register specifies the number of the next data item to be read. Thus,
by changing POS, the user can backspace or advance the reader.
The paper tape reader requires an unsupported driver under TOPS-10
and is not supported under TOPS-20 or ITS.
The paper tape reader implements these registers:
name size comments
BUF 8 last data item processed
CSR 16 control/status register
INT 1 interrupt pending flag
ERR 1 error flag (CSR<15>)
BUSY 1 busy flag (CSR<11>)
DONE 1 device done flag (CSR<7>)
IE 1 interrupt enable flag (CSR<6>)
POS 32 position in the input file
TIME 24 time from I/O initiation to interrupt
STOP_IOE 1 stop on I/O error
Error handling is as follows:
error STOP_IOE processed as
not attached 1 report error and stop
0 out of tape
end of file 1 report error and stop
0 out of tape
OS I/O error x report error and stop
2.7 PC11 Paper Tape Punch (PTP)
The paper tape punch (PTP) writes data to a disk file. The POS
register specifies the number of the next data item to be written.
Thus, by by changing POS, the user can backspace or advance the punch.
The paper tape punch requires an unsupported driver under TOPS-10
and is not supported under TOPS-20 or ITS.
The paper tape punch implements these registers:
name size comments
BUF 8 last data item processed
CSR 16 control/status register
INT 1 interrupt pending flag
ERR 1 error flag (CSR<15>)
DONE 1 device done flag (CSR<7>)
IE 1 interrupt enable flag (CSR<6>)
POS 32 position in the input or output file
TIME 24 time from I/O initiation to interrupt
STOP_IOE 1 stop on I/O error
Error handling is as follows:
error STOP_IOE processed as
not attached 1 report error and stop
0 out of tape
OS I/O error x report error and stop
2.8 DZ11 Terminal Multiplexor (DZ)
The DZ11 is an 8-line terminal multiplexor. Up to 4 DZ11's (32 lines)
are supported. The number of lines can be changed with the command
SET DZ LINES=n set line count to n
The line count must be a multiple of 8, with a maximum of 32.
The DZ11 supports three character processing modes, 7P, 7B, and 8B:
mode input characters output characters
7P high-order bit cleared high-order bit cleared,
non-printing characters
suppressed
7B high-order bit cleared high-order bit cleared
8B no changes no changes
The default is 7B, for compatability with TOPS-20.
The DZ11 supports logging on a per-line basis. The command
SET DZ LOG=line=filename
enables logging for the specified line to the indicated file. The
command
SET DZ NOLOG=line
disables logging for the specified line and closes any open log file.
Finally, the command
SHOW DZ LOG
displays logging information for all DZ lines.
The terminal lines perform input and output through Telnet sessions
connected to a user-specified port. The ATTACH command specifies
the port to be used:
ATTACH {-am} DZ <port> set up listening port
where port is a decimal number between 1 and 65535 that is not being used
for other TCP/IP activities. The optional switch -m turns on the DZ11's
modem controls; the optional switch -a turns on active disconnects
(disconnect session if computer clears Data Terminal Ready). Without
modem control, the DZ behaves as though terminals were directly connected;
disconnecting the Telnet session does not cause any operating system-
visible change in line status.
Once the DZ is attached and the simulator is running, the DZ will listen
for connections on the specified port. It assumes that the incoming
connections are Telnet connections. The connection remains open until
disconnected by the simulated program, the Telnet client, a SET DZ
DISCONNECT command, or a DETACH DZ command.
The SHOW DZ CONNECTIONS command displays the current connections to the DZ.
The SHOW DZ STATISTICS command displays statistics for active connections.
The SET DZ DISCONNECT=linenumber command disconnects the specified line.
The DZ11 implements these registers:
name size comments
CSR[0:3] 16 control/status register, boards 0-3
RBUF[0:3] 16 receive buffer, boards 0-3
LPR[0:3] 16 line parameter register, boards 0-3
TCR[0:3] 16 transmission control register, boards 0-3
MSR[0:3] 16 modem status register, boards 0-3
TDR[0:3] 16 transmit data register, boards 0-3
SAENB[0:3] 1 silo alarm enabled, boards 0-3
RXINT 4 receive interrupts, boards 3..0
TXINT 4 transmit interrupts, boards 3..0
MDMTCL 1 modem control enabled
AUTODS 1 autodisconnect enabled
The DZ11 does not support save and restore. All open connections are
lost when the simulator shuts down or the DZ is detached.
2.9 RH11 Adapter, RM02/03/05/80, RP04/05/06/07 drives (RP)
The RP controller implements the Massbus 18b (RH11) direct interface for
large disk drives. It is more abstract than other device simulators, with
just enough detail to run operating system drivers. In addition, the RP
controller conflates the details of the RM series controllers with the RP
series controllers, although there were detailed differences.
RP options include the ability to set units write enabled or write locked,
to set the drive type to one of six disk types, or autosize:
SET RPn LOCKED set unit n write locked
SET RPn WRITEENABLED set unit n write enabled
SET RPn RM03 set type to RM03
SET RPn RM05 set type to RM05
SET RPn RM80 set type to RM80
SET RPn RP04 set type to RP04
SET RPn RP06 set type to RP06
SET RPn RP07 set type to RP07
SET RPn AUTOSIZE set type based on file size at attach
The type options can be used only when a unit is not attached to a file.
Note that TOPS-10 V7.03 supported only the RP06 and RM03; V7.04 added
support for the RP07. TOPS-20 V4.1 also supported only the RP06 and
RM03. Units can be set ENABLED or DISABLED.
The RP controller implements these registers:
name size comments
RPCS1 16 control/status 1
RPWC 16 word count
RPBA 16 bus address
RPDA 16 desired surface, sector
RPCS2 16 control/status 2
RPDS[0:7] 16 drive status, drives 0-7
RPER1[0:7] 16 drive errors, drives 0-7
RPOF 16 offset
RPDC 8 desired cylinder
RPER2 16 error status 2
RPER3 16 error status 3
RPEC1 16 ECC syndrome 1
RPEC2 16 ECC syndrome 2
RPMR 16 maintenance register
RPDB 16 data buffer
IFF 1 transfer complete interrupt request flop
INT 1 interrupt pending flag
SC 1 special condition (CSR1<15>)
DONE 1 device done flag (CSR1<7>)
IE 1 interrupt enable flag (CSR1<6>)
STIME 24 seek time, per cylinder
RTIME 24 rotational delay
STOP_IOE 1 stop on I/O error
Error handling is as follows:
error STOP_IOE processed as
not attached 1 report error and stop
0 disk not ready
end of file x assume rest of disk is zero
OS I/O error x report error and stop
2.10 RH11 Adapter, TM02 Formatter, TU45 Magnetic Tape (TU)
The magnetic tape simulator simulates an RH11 Massbus adapter with one
TM02 formatter and up to eight TU45 drives. Magnetic tape options include
the ability to make units write enabled or locked.
SET TUn LOCKED set unit n write locked
SET TUn WRITEENABLED set unit n write enabled
Units can also be set ENABLED or DISABLED.
The magnetic tape controller implements these registers:
name size comments
MTCS1 16 control/status 1
MTBA 16 memory address
MTWC 16 word count
MTFC 16 frame count
MTCS2 16 control/status 2
MTFS 16 formatter status
MTER 16 error status
MTCC 16 check character
MTDB 16 data buffer
MTMR 16 maintenance register
MTTC 16 tape control register
INT 1 interrupt pending flag
DONE 1 device done flag
IE 1 interrupt enable flag
STOP_IOE 1 stop on I/O error
TIME 24 delay
UST[0:7] 16 unit status, units 0-7
POS[0:7] 32 position, units 0-7
Error handling is as follows:
error processed as
not attached tape not ready; if STOP_IOE, stop
end of file operation incomplete
OS I/O error parity error; if STOP_IOE, stop
2.11 LP20 DMA Line Printer (LP20)
The LP20 is a DMA-based line printer controller. There is one
line printer option to clear the vertical forms unit (VFU):
SET LP20 VFUCLEAR clear the vertical forms unit
The LP20 implements these registers:
name size comments
LPCSA 16 control/status register A
LPCSB 16 control/status register B
LPBA 16 bus address register
LPBC 12 byte count register
LPPAGC 12 page count register
LPRDAT 12 RAM data register
LPCBUF 8 character buffer register
LPCOLC 8 column counter register
LPPDAT 8 printer data register
LPCSUM 8 checksum register
DVPTR 7 vertical forms unit pointer
DVLNT 7 vertical forms unit length
INT 1 interrupt request
ERR 1 error flag
DONE 1 done flag
IE 1 interrupt enable flag
POS 32 position in output file
TIME 24 response time
STOP_IOE 1 stop on I/O error
TXRAM[0:255] 12 translation RAM
DAVFU[0:142] 12 vertical forms unit array
Error handling is as follows:
error STOP_IOE processed as
not attached 1 report error and stop
0 out of paper
OS I/O error x report error and stop
2.12 RX211/RX02 Floppy Disk (RY)
RX211 options include the ability to set units write enabled or write
locked, single or double density, or autosized:
SET RYn LOCKED set unit n write locked
SET RYn WRITEENABLED set unit n write enabled
SET RYn SINGLE set unit n single density
SET RYn DOUBLE set unit n double density (default)
SET RYn AUTOSIZE set unit n autosized
The floppy disk requires an unsupported driver under TOPS-10 and
is not supported under TOPS-20 or ITS.
The RX211 implements these registers:
name size comments
RYCS 16 status
RYBA 16 buffer address
RYWC 8 word count
RYDB 16 data buffer
RYES 12 error status
RYERR 8 error code
RYTA 8 current track
RYSA 8 current sector
STAPTR 4 controller state
INT 1 interrupt pending flag
ERR 1 error flag (CSR<15>)
TR 1 transfer ready flag (CSR<7>)
IE 1 interrupt enable flag (CSR<6>)
DONE 1 device done flag (CSR<5>)
CTIME 24 command completion time
STIME 24 seek time, per track
XTIME 24 transfer ready delay
STOP_IOE 1 stop on I/O error
SBUF[0:255] 8 sector buffer array
Error handling is as follows:
error STOP_IOE processed as
not attached 1 report error and stop
0 disk not ready
RX02 data files are buffered in memory; therefore, end of file and OS
I/O errors cannot occur.
2.13 DEUNA/DELUA Ethernet Controller (XU)
XU simulates the DEUNA/DELUA Ethernet controller. The current implementation
is a stub and is permanently disabled.
2.14 Symbolic Display and Input
The PDP-10 simulator implements symbolic display and input. Display is
controlled by command line switches:
-a display as ASCII character
-c display as (sixbit) character string
-p display as packed (seven bit) string
-m display instruction mnemonics
-v interpret address as virtual
-e force executive mode
-u force user mode
Input parsing is controlled by the first character typed in or by command
line switches:
' or -a ASCII character
" or -c sixbit string
# or -p packed seven bit string
alphabetic instruction mnemonic
numeric octal number
Instruction input uses standard PDP-10 assembler syntax. There are three
instruction classes: memory reference, memory reference with AC, and I/O.
Memory reference instructions have the format
memref {@}address{(index)}
memory reference with AC instructions have the format
memac ac,{@}address{(index)}
and I/O instructions have the format
io device,{@}address{(index)}
where @ signifies indirect. The address is a signed octal number in the
range 0 - 0777777. The ac and index are unsigned octal numbers in the
range 0-17. The device is either a recognized device mnemonic (APR, PI,
TIM) or an octal number in the range 0 - 0177.
The simulator recognizes the standard MACRO alternate mnemonics (CLEAR
for SETZ, OR for IORI), the individual definitions for JRST and JFCL
variants, and the extended instruction mnemonics.

View file

@ -1,6 +1,6 @@
/* pdp10_tu.c - PDP-10 RH11/TM03/TU45 magnetic tape simulator /* pdp10_tu.c - PDP-10 RH11/TM03/TU45 magnetic tape simulator
Copyright (c) 1993-2005, Robert M Supnik Copyright (c) 1993-2006, Robert M Supnik
Permission is hereby granted, free of charge, to any person obtaining a Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"), copy of this software and associated documentation files (the "Software"),
@ -25,6 +25,7 @@
tu RH11/TM03/TU45 magtape tu RH11/TM03/TU45 magtape
16-Feb-06 RMS Added tape capacity checking
16-Aug-05 RMS Fixed C++ declaration and cast problems 16-Aug-05 RMS Fixed C++ declaration and cast problems
07-Jul-05 RMS Removed extraneous externs 07-Jul-05 RMS Removed extraneous externs
31-Mar-05 RMS Fixed bug, ERASE/WREOF incorrectly clear CS1<done> 31-Mar-05 RMS Fixed bug, ERASE/WREOF incorrectly clear CS1<done>
@ -399,6 +400,8 @@ MTAB tu_mod[] = {
{ MTUF_WLK, MTUF_WLK, "write locked", "LOCKED", NULL }, { MTUF_WLK, MTUF_WLK, "write locked", "LOCKED", NULL },
{ MTAB_XTD|MTAB_VUN, 0, "FORMAT", "FORMAT", { MTAB_XTD|MTAB_VUN, 0, "FORMAT", "FORMAT",
&sim_tape_set_fmt, &sim_tape_show_fmt, NULL }, &sim_tape_set_fmt, &sim_tape_show_fmt, NULL },
{ MTAB_XTD|MTAB_VUN, 0, "CAPACITY", "CAPACITY",
&sim_tape_set_capac, &sim_tape_show_capac, NULL },
{ MTAB_XTD|MTAB_VDV, 0, "ADDRESS", NULL, { MTAB_XTD|MTAB_VDV, 0, "ADDRESS", NULL,
NULL, &show_addr, NULL }, NULL, &show_addr, NULL },
{ MTAB_XTD|MTAB_VDV, 0, "VECTOR", NULL, { MTAB_XTD|MTAB_VDV, 0, "VECTOR", NULL,
@ -625,7 +628,7 @@ return SCPE_OK;
void tu_go (int32 drv) void tu_go (int32 drv)
{ {
int32 fnc, den, space_test = FS_BOT; int32 fnc, den;
UNIT *uptr; UNIT *uptr;
fnc = GET_FNC (tucs1); /* get function */ fnc = GET_FNC (tucs1); /* get function */
@ -687,13 +690,23 @@ switch (fnc) { /* case on function */
return; return;
case FNC_SPACEF: case FNC_SPACEF:
space_test = FS_EOT; if ((uptr->flags & UNIT_ATT) == 0) { /* unattached? */
set_tuer (ER_UNS);
break;
}
if (sim_tape_eot (uptr) || ((tutc & TC_FCS) == 0)) {
set_tuer (ER_NXF);
break;
}
uptr->USTAT = FS_PIP;
goto GO_XFER;
case FNC_SPACER: case FNC_SPACER:
if ((uptr->flags & UNIT_ATT) == 0) { /* unattached? */ if ((uptr->flags & UNIT_ATT) == 0) { /* unattached? */
set_tuer (ER_UNS); set_tuer (ER_UNS);
break; break;
} }
if ((tufs & space_test) || ((tutc & TC_FCS) == 0)) { if (sim_tape_bot (uptr) || ((tutc & TC_FCS) == 0)) {
set_tuer (ER_NXF); set_tuer (ER_NXF);
break; break;
} }
@ -807,7 +820,7 @@ switch (fnc) { /* case on function */
r = tu_map_err (uptr, st, 0); /* map error */ r = tu_map_err (uptr, st, 0); /* map error */
break; break;
} }
} while (tufc != 0); } while ((tufc != 0) && !sim_tape_eot (uptr));
if (tufc) set_tuer (ER_FCE); if (tufc) set_tuer (ER_FCE);
else tutc = tutc & ~TC_FCS; else tutc = tutc & ~TC_FCS;
tufs = tufs | FS_ATA; tufs = tufs | FS_ATA;
@ -977,7 +990,10 @@ if (GET_FMTR (tucs2) == 0) { /* formatter present? */
tufs = tufs | FS_MOL | tu_unit[drv].USTAT; tufs = tufs | FS_MOL | tu_unit[drv].USTAT;
if (tu_unit[drv].UDENS == TC_1600) tufs = tufs | FS_PE; if (tu_unit[drv].UDENS == TC_1600) tufs = tufs | FS_PE;
if (sim_tape_wrp (&tu_unit[drv])) tufs = tufs | FS_WRL; if (sim_tape_wrp (&tu_unit[drv])) tufs = tufs | FS_WRL;
if (sim_tape_bot (&tu_unit[drv]) && !act) tufs = tufs | FS_BOT; if (!act) {
if (sim_tape_bot (&tu_unit[drv])) tufs = tufs | FS_BOT;
if (sim_tape_eot (&tu_unit[drv])) tufs = tufs | FS_EOT;
}
} }
if (tuer) tufs = tufs | FS_ERR; if (tuer) tufs = tufs | FS_ERR;
} }

View file

@ -1,6 +1,6 @@
/* pdp11_cis.c: PDP-11 CIS optional instruction set simulator /* pdp11_cis.c: PDP-11 CIS optional instruction set simulator
Copyright (c) 1993-2005, Robert M Supnik Copyright (c) 1993-2006, Robert M Supnik
Permission is hereby granted, free of charge, to any person obtaining a Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"), copy of this software and associated documentation files (the "Software"),
@ -25,6 +25,10 @@
This module simulates the PDP-11 commercial instruction set (CIS). This module simulates the PDP-11 commercial instruction set (CIS).
22-May-06 RMS Fixed bug in decode table (found by John Dundas)
Fixed bug in ASHP (reported by John Dundas)
Fixed bug in write decimal string with mmgt enabled
Fixed bug in 0-length strings in multiply/divide
16-Sep-04 RMS Fixed bug in CMPP/N of negative strings 16-Sep-04 RMS Fixed bug in CMPP/N of negative strings
17-Oct-02 RMS Fixed compiler warning (found by Hans Pufal) 17-Oct-02 RMS Fixed compiler warning (found by Hans Pufal)
08-Oct-02 RMS Fixed macro definitions 08-Oct-02 RMS Fixed macro definitions
@ -175,7 +179,7 @@ void SubDstr (DSTR *src1, DSTR *src2, DSTR *dst);
int32 CmpDstr (DSTR *src1, DSTR *src2); int32 CmpDstr (DSTR *src1, DSTR *src2);
int32 TestDstr (DSTR *dsrc); int32 TestDstr (DSTR *dsrc);
int32 LntDstr (DSTR *dsrc, int32 nz); int32 LntDstr (DSTR *dsrc, int32 nz);
uint32 NibbleLshift (DSTR *dsrc, int32 sc, uint32 cin); uint32 NibbleLshift (DSTR *dsrc, int32 sc);
uint32 NibbleRshift (DSTR *dsrc, int32 sc, uint32 cin); uint32 NibbleRshift (DSTR *dsrc, int32 sc, uint32 cin);
int32 WordLshift (DSTR *dsrc, int32 sc); int32 WordLshift (DSTR *dsrc, int32 sc);
void WordRshift (DSTR *dsrc, int32 sc); void WordRshift (DSTR *dsrc, int32 sc);
@ -269,7 +273,7 @@ static int32 opntab[128][MAXOPN] = {
IN_DESC, IN_DESC, IN_DESC, 0, /* ADDPI */ IN_DESC, IN_DESC, IN_DESC, 0, /* ADDPI */
IN_DESC, IN_DESC, IN_DESC, 0, /* SUBPI */ IN_DESC, IN_DESC, IN_DESC, 0, /* SUBPI */
IN_DESC, IN_DESC, 0, 0, /* CMPPI */ IN_DESC, IN_DESC, 0, 0, /* CMPPI */
IN_DESC, 0, 0, 0, /* CVTPLI */ IN_DESC, IN_ARG, 0, 0, /* CVTPLI */
IN_DESC, IN_DESC, IN_DESC, 0, /* MULPI */ IN_DESC, IN_DESC, IN_DESC, 0, /* MULPI */
IN_DESC, IN_DESC, IN_DESC, 0, /* DIVPI */ IN_DESC, IN_DESC, IN_DESC, 0, /* DIVPI */
IN_DESC, IN_DESC, IN_ARG, 0, /* ASHPI */ IN_DESC, IN_DESC, IN_ARG, 0, /* ASHPI */
@ -357,8 +361,8 @@ for (i = j = 0; (i < MAXOPN) && opntab[op][i]; i++) { /* parse operands */
R[0] = ReadW (addr | dsenable); R[0] = ReadW (addr | dsenable);
R[1] = ReadW (((addr + 2) & 0177777) | dsenable); R[1] = ReadW (((addr + 2) & 0177777) | dsenable);
break; break;
case IN_ARG:
case IN_ARG:
arg[j++] = ReadW (PC | isenable); arg[j++] = ReadW (PC | isenable);
PC = (PC + 2) & 0177777; PC = (PC + 2) & 0177777;
break; break;
@ -729,7 +733,7 @@ switch (op) { /* case on opcode */
NibbleRshift (&src2, 1, 0); NibbleRshift (&src2, 1, 0);
if ((t = ldivd - ldivr) >= 0) { /* any divide to do? */ if ((t = ldivd - ldivr) >= 0) { /* any divide to do? */
WordLshift (&src1, t / 8); /* align divr to divd */ WordLshift (&src1, t / 8); /* align divr to divd */
NibbleLshift (&src1, t % 8, 0); NibbleLshift (&src1, t % 8);
CreateTable (&src1, mptable); /* create *1, *2, ... */ CreateTable (&src1, mptable); /* create *1, *2, ... */
for (i = 0; i <= t; i++) { /* divide loop */ for (i = 0; i <= t; i++) { /* divide loop */
for (digit = 9; digit > 0; digit--) { /* find digit */ for (digit = 9; digit > 0; digit--) { /* find digit */
@ -739,8 +743,8 @@ switch (op) { /* case on opcode */
break; break;
} /* end if */ } /* end if */
} /* end for */ } /* end for */
NibbleLshift (&src2, 1, 0); /* shift dividend */ NibbleLshift (&src2, 1); /* shift dividend */
NibbleLshift (&dst, 1, 0); /* shift quotient */ NibbleLshift (&dst, 1); /* shift quotient */
} /* end divide loop */ } /* end divide loop */
dst.sign = src1.sign ^ src2.sign; /* calculate sign */ dst.sign = src1.sign ^ src2.sign; /* calculate sign */
} /* end if */ } /* end if */
@ -810,7 +814,7 @@ switch (op) { /* case on opcode */
} /* end right shift */ } /* end right shift */
else if (shift) { /* left shift? */ else if (shift) { /* left shift? */
if (WordLshift (&src1, shift / 8)) V = 1; /* do word shifts */ if (WordLshift (&src1, shift / 8)) V = 1; /* do word shifts */
if (NibbleLshift (&src1, shift % 8, 0)) V = 1; if (NibbleLshift (&src1, shift % 8)) V = 1;
} /* end left shift */ } /* end left shift */
WriteDstr (A2, &src1, op); /* store result */ WriteDstr (A2, &src1, op); /* store result */
if ((op & INLINE) == 0) /* if reg, clr reg */ if ((op & INLINE) == 0) /* if reg, clr reg */
@ -1056,7 +1060,7 @@ if (flag & PACKED) { /* packed? */
else dst->val[0] = dst->val[0] | 0xC | dst->sign; else dst->val[0] = dst->val[0] | 0xC | dst->sign;
for (i = 0; i <= end; i++) { /* store string */ for (i = 0; i <= end; i++) { /* store string */
c = (dst->val[i / 4] >> ((i % 4) * 8)) & 0xFF; c = (dst->val[i / 4] >> ((i % 4) * 8)) & 0xFF;
WriteB (c, ((dscr[1] + end - i) & 0177777)); WriteB (c, ((dscr[1] + end - i) & 0177777) | dsenable);
} /* end for */ } /* end for */
} /* end packed */ } /* end packed */
else { else {
@ -1070,7 +1074,7 @@ else {
((i == lnt) && (type == LO))) ((i == lnt) && (type == LO)))
c = binover[dst->sign][c]; /* get sign and digit */ c = binover[dst->sign][c]; /* get sign and digit */
else c = c | 0x30; /* default */ else c = c | 0x30; /* default */
WriteB (c, ((dscr[1] + lnt - i) & 0177777)); WriteB (c, ((dscr[1] + lnt - i) & 0177777) |dsenable );
} /* end for */ } /* end for */
} /* end numeric */ } /* end numeric */
return; return;
@ -1201,6 +1205,7 @@ int32 LntDstr (DSTR *dsrc, int32 nz)
{ {
int32 i; int32 i;
if (nz == 0) return 0;
for (i = 7; i > 0; i--) { for (i = 7; i > 0; i--) {
if ((dsrc->val[nz - 1] >> (i * 4)) & 0xF) break; if ((dsrc->val[nz - 1] >> (i * 4)) & 0xF) break;
} }
@ -1299,22 +1304,22 @@ return 0;
Arguments: Arguments:
dsrc = decimal string structure dsrc = decimal string structure
sc = shift count sc = shift count
cin = carry in
*/ */
uint32 NibbleLshift (DSTR *dsrc, int32 sc, uint32 cin) uint32 NibbleLshift (DSTR *dsrc, int32 sc)
{ {
int32 i, s, rs, nc; int32 i, s, rs;
uint32 sv_val, cout;
cout = 0;
if (s = sc * 4) { if (s = sc * 4) {
rs = 32 - s; rs = 32 - s;
for (i = 0; i < DSTRLNT; i++) { for (i = 0; i < DSTRLNT; i++) {
nc = dsrc->val[i]; sv_val = dsrc->val[i];
dsrc->val[i] = ((dsrc->val[i] << s) | dsrc->val[i] = ((dsrc->val[i] << s) | cout) & 0xFFFFFFFF;
(cin >> rs)) & 0xFFFFFFFF; cout = sv_val >> rs;
cin = nc;
} }
return cin; return cout;
} }
return 0; return 0;
} }

View file

@ -1,6 +1,6 @@
/* pdp11_cpu.c: PDP-11 CPU simulator /* pdp11_cpu.c: PDP-11 CPU simulator
Copyright (c) 1993-2005, Robert M Supnik Copyright (c) 1993-2006, Robert M Supnik
Permission is hereby granted, free of charge, to any person obtaining a Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"), copy of this software and associated documentation files (the "Software"),
@ -25,6 +25,8 @@
cpu PDP-11 CPU cpu PDP-11 CPU
24-May-06 RMS Added instruction history
03-May-06 RMS Fixed XOR operand fetch order for 11/70-style systems
22-Sep-05 RMS Fixed declarations (from Sterling Garwood) 22-Sep-05 RMS Fixed declarations (from Sterling Garwood)
16-Aug-05 RMS Fixed C++ declaration and cast problems 16-Aug-05 RMS Fixed C++ declaration and cast problems
19-May-05 RMS Replaced WAIT clock queue check with API call 19-May-05 RMS Replaced WAIT clock queue check with API call
@ -228,6 +230,19 @@
#define UNIT_V_MSIZE (UNIT_V_UF + 0) /* dummy */ #define UNIT_V_MSIZE (UNIT_V_UF + 0) /* dummy */
#define UNIT_MSIZE (1u << UNIT_V_MSIZE) #define UNIT_MSIZE (1u << UNIT_V_MSIZE)
#define HIST_MIN 64
#define HIST_MAX (1u << 18)
#define HIST_VLD 1 /* make PC odd */
#define HIST_ILNT 4 /* max inst length */
typedef struct {
uint16 pc;
uint16 psw;
uint16 src;
uint16 dst;
uint16 inst[HIST_ILNT];
} InstHistory;
/* Global state */ /* Global state */
extern FILE *sim_log; extern FILE *sim_log;
@ -274,12 +289,16 @@ uint16 pcq[PCQ_SIZE] = { 0 }; /* PC queue */
int32 pcq_p = 0; /* PC queue ptr */ int32 pcq_p = 0; /* PC queue ptr */
REG *pcq_r = NULL; /* PC queue reg ptr */ REG *pcq_r = NULL; /* PC queue reg ptr */
jmp_buf save_env; /* abort handler */ jmp_buf save_env; /* abort handler */
int32 hst_p = 0; /* history pointer */
int32 hst_lnt = 0; /* history length */
InstHistory *hst = NULL; /* instruction history */
int32 dsmask[4] = { MMR3_KDS, MMR3_SDS, 0, MMR3_UDS }; /* dspace enables */ int32 dsmask[4] = { MMR3_KDS, MMR3_SDS, 0, MMR3_UDS }; /* dspace enables */
extern int32 CPUERR, MAINT; extern int32 CPUERR, MAINT;
extern int32 sim_interval; extern int32 sim_interval;
extern UNIT clk_unit, pclk_unit; extern UNIT clk_unit, pclk_unit;
extern int32 sim_int_char; extern int32 sim_int_char;
extern uint32 sim_switches;
extern uint32 sim_brk_types, sim_brk_dflt, sim_brk_summ; /* breakpoint info */ extern uint32 sim_brk_types, sim_brk_dflt, sim_brk_summ; /* breakpoint info */
extern DEVICE *sim_devices[]; extern DEVICE *sim_devices[];
extern CPUTAB cpu_tab[]; extern CPUTAB cpu_tab[];
@ -289,6 +308,9 @@ extern CPUTAB cpu_tab[];
t_stat cpu_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw); t_stat cpu_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw);
t_stat cpu_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw); t_stat cpu_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw);
t_stat cpu_reset (DEVICE *dptr); t_stat cpu_reset (DEVICE *dptr);
t_stat cpu_set_hist (UNIT *uptr, int32 val, char *cptr, void *desc);
t_stat cpu_show_hist (FILE *st, UNIT *uptr, int32 val, void *desc);
t_stat cpu_show_virt (FILE *st, UNIT *uptr, int32 val, void *desc);
int32 GeteaB (int32 spec); int32 GeteaB (int32 spec);
int32 GeteaW (int32 spec); int32 GeteaW (int32 spec);
int32 relocR (int32 addr); int32 relocR (int32 addr);
@ -586,6 +608,10 @@ MTAB cpu_mod[] = {
&set_autocon, &show_autocon }, &set_autocon, &show_autocon },
{ MTAB_XTD|MTAB_VDV, 0, NULL, "NOAUTOCONFIG", { MTAB_XTD|MTAB_VDV, 0, NULL, "NOAUTOCONFIG",
&set_autocon, NULL }, &set_autocon, NULL },
{ MTAB_XTD|MTAB_VDV|MTAB_NMO|MTAB_SHP, 0, "HISTORY", "HISTORY",
&cpu_set_hist, &cpu_show_hist },
{ MTAB_XTD|MTAB_VDV|MTAB_NMO|MTAB_SHP, 0, "VIRTUAL", NULL,
NULL, &cpu_show_virt },
{ 0 } { 0 }
}; };
@ -775,12 +801,28 @@ while (reason == 0) {
MMR2 = PC; MMR2 = PC;
} }
IR = ReadE (PC | isenable); /* fetch instruction */ IR = ReadE (PC | isenable); /* fetch instruction */
PC = (PC + 2) & 0177777; /* incr PC, mod 65k */
sim_interval = sim_interval - 1; sim_interval = sim_interval - 1;
srcspec = (IR >> 6) & 077; /* src, dst specs */ srcspec = (IR >> 6) & 077; /* src, dst specs */
dstspec = IR & 077; dstspec = IR & 077;
srcreg = (srcspec <= 07); /* src, dst = rmode? */ srcreg = (srcspec <= 07); /* src, dst = rmode? */
dstreg = (dstspec <= 07); dstreg = (dstspec <= 07);
if (hst_lnt) { /* record history? */
t_value val;
uint32 i;
hst[hst_p].pc = PC | HIST_VLD;
hst[hst_p].psw = get_PSW ();
hst[hst_p].src = R[srcspec & 07];
hst[hst_p].dst = R[dstspec & 07];
hst[hst_p].inst[0] = IR;
for (i = 1; i < HIST_ILNT; i++) {
if (cpu_ex (&val, (PC + (i << 1)) & 0177777, &cpu_unit, SWMASK ('V')))
hst[hst_p].inst[i] = 0;
else hst[hst_p].inst[i] = (uint16) val;
}
hst_p = (hst_p + 1);
if (hst_p >= hst_lnt) hst_p = 0;
}
PC = (PC + 2) & 0177777; /* incr PC, mod 65k */
switch ((IR >> 12) & 017) { /* decode IR<15:12> */ switch ((IR >> 12) & 017) { /* decode IR<15:12> */
/* Opcode 0: no operands, specials, branches, JSR, SOPs */ /* Opcode 0: no operands, specials, branches, JSR, SOPs */
@ -1478,8 +1520,15 @@ while (reason == 0) {
case 4: /* XOR */ case 4: /* XOR */
if (CPUT (HAS_SXS)) { if (CPUT (HAS_SXS)) {
dst = dstreg? R[dstspec]: ReadMW (GeteaW (dstspec)); if (CPUT (IS_SDSD) && !dstreg) { /* R,not R */
dst = dst ^ R[srcspec]; src2 = ReadMW (GeteaW (dstspec));
src = R[srcspec];
}
else {
src = R[srcspec];
src2 = dstreg? R[dstspec]: ReadMW (GeteaW (dstspec));
}
dst = src ^ src2;
N = GET_SIGN_W (dst); N = GET_SIGN_W (dst);
Z = GET_Z (dst); Z = GET_Z (dst);
V = 0; V = 0;
@ -2835,3 +2884,96 @@ for (i = 0; i < 6; i++, rptr++) rptr->loc = (void *) &REGFILE[i][rs];
rptr->loc = (void *) &STACKFILE[cm]; rptr->loc = (void *) &STACKFILE[cm];
return; return;
} }
/* Set history */
t_stat cpu_set_hist (UNIT *uptr, int32 val, char *cptr, void *desc)
{
int32 i, lnt;
t_stat r;
if (cptr == NULL) {
for (i = 0; i < hst_lnt; i++) hst[i].pc = 0;
hst_p = 0;
return SCPE_OK;
}
lnt = (int32) get_uint (cptr, 10, HIST_MAX, &r);
if ((r != SCPE_OK) || (lnt && (lnt < HIST_MIN))) return SCPE_ARG;
hst_p = 0;
if (hst_lnt) {
free (hst);
hst_lnt = 0;
hst = NULL;
}
if (lnt) {
hst = (InstHistory *) calloc (lnt, sizeof (InstHistory));
if (hst == NULL) return SCPE_MEM;
hst_lnt = lnt;
}
return SCPE_OK;
}
/* Show history */
t_stat cpu_show_hist (FILE *st, UNIT *uptr, int32 val, void *desc)
{
int32 j, k, di, lnt, ir;
char *cptr = (char *) desc;
t_value sim_eval[HIST_ILNT];
t_stat r;
InstHistory *h;
extern t_stat fprint_sym (FILE *ofile, t_addr addr, t_value *val,
UNIT *uptr, int32 sw);
if (hst_lnt == 0) return SCPE_NOFNC; /* enabled? */
if (cptr) {
lnt = (int32) get_uint (cptr, 10, hst_lnt, &r);
if ((r != SCPE_OK) || (lnt == 0)) return SCPE_ARG;
}
else lnt = hst_lnt;
di = hst_p - lnt; /* work forward */
if (di < 0) di = di + hst_lnt;
fprintf (st, "PC PSW src dst IR\n\n");
for (k = 0; k < lnt; k++) { /* print specified */
h = &hst[(di++) % hst_lnt]; /* entry pointer */
if (h->pc & HIST_VLD) { /* instruction? */
ir = h->inst[0];
fprintf (st, "%06o %06o|", h->pc & ~HIST_VLD, h->psw);
if (((ir & 0070000) != 0) || /* dops, eis, fpp */
((ir & 0177000) == 0004000)) /* jsr */
fprintf (st, "%06o %06o ", h->src, h->dst);
else if ((ir >= 0000100) && /* not no opnd */
(((ir & 0007700) < 0000300) || /* not branch */
((ir & 0007700) >= 0004000)))
fprintf (st, " %06o ", h->dst);
else fprintf (st, " ");
for (j = 0; j < HIST_ILNT; j++) sim_eval[j] = h->inst[j];
if ((fprint_sym (st, h->pc & ~HIST_VLD, sim_eval, &cpu_unit, SWMASK ('M'))) > 0)
fprintf (st, "(undefined) %06o", h->inst[0]);
fputc ('\n', st); /* end line */
} /* end else instruction */
} /* end for */
return SCPE_OK;
}
/* Virtual address translation */
t_stat cpu_show_virt (FILE *of, UNIT *uptr, int32 val, void *desc)
{
t_stat r;
char *cptr = (char *) desc;
uint32 va, pa;
if (cptr) {
va = (uint32) get_uint (cptr, 8, VAMASK, &r);
if (r == SCPE_OK) {
pa = relocC (va, sim_switches); /* relocate */
if (pa < MAXMEMSIZE)
fprintf (of, "Virtual %-o = physical %-o\n", va, pa);
else fprintf (of, "Virtual %-o is not valid\n", va);
return SCPE_OK;
}
}
fprintf (of, "Invalid argument\n");
return SCPE_OK;
}

1272
PDP11/pdp11_cr.c Normal file

File diff suppressed because it is too large Load diff

622
PDP11/pdp11_cr_dat.h Normal file
View file

@ -0,0 +1,622 @@
/* pdp11_cr_dat.h
*
* card code arrays are indexed by 7-bit ASCII code, and
* give corresponding 12-bit card codes using the indicated
* collating sequence.
*
* ERROR should be externally defined, either as an illegal
* card code (on conversion from ASCII to card codes) or as
* a code with a bit set outside the least significant 12.
*
* author: Douglas Jones, jones@cs.uiowa.edu
* revisions:
* March 5, 1996
* Feb 18, 1997 to add 026 and EBCDIC converstion tables
* Jan 10, 2005, (JAD) Added 'static const' to the array
* definitions.
* Jan 11, 2005, (JAD) Create the h2c_code array.
* Jan 14, 2005, (JAD) Added the special DEC code for 'end of deck'
* (12-11-0-1-6-7-8-9) to the o29_code array at position 26. (^Z).
* Should I add this to the other arrays?
*/
/* DEC's version of the IBM 029 kepunch encoding, (thus avoiding IBM's
use of non-ASCII punctuation), based on that given in the appendix
to Digital's "Small Computer Handbook, 1973", and augmented to
translate lower case to upper case. As a result of this modification,
inversion of this table should be done with care! */
static const int o29_code[] = {
ERROR,ERROR,ERROR,ERROR,ERROR,ERROR,ERROR,ERROR, /* control */
ERROR,ERROR,ERROR,ERROR,ERROR,ERROR,ERROR,ERROR, /* chars */
ERROR,ERROR,ERROR,ERROR,ERROR,ERROR,ERROR,ERROR, /* control */
ERROR,ERROR,07417,ERROR,ERROR,ERROR,ERROR,ERROR, /* chars */
00000,02202,00006,00102,02102,01042,04000,00022, /* !"#$%&' */
04022,02022,02042,04012,01102,02000,04102,01400, /* ()*+,-./ */
01000,00400,00200,00100,00040,00020,00010,00004, /* 01234567 */
00002,00001,00202,02012,04042,00012,01012,01006, /* 89:;<=>? */
00042,04400,04200,04100,04040,04020,04010,04004, /* @ABCDEFG */
04002,04001,02400,02200,02100,02040,02020,02010, /* HIJKLMNO */
02004,02002,02001,01200,01100,01040,01020,01010, /* PQRSTUVW */
01004,01002,01001,04202,02006,01202,04006,01022, /* XYZ[\]^_ */
ERROR,04400,04200,04100,04040,04020,04010,04004, /* `abcdefg */
04002,04001,02400,02200,02100,02040,02020,02010, /* hijklmno */
02004,02002,02001,01200,01100,01040,01020,01010, /* pqrstuvw */
01004,01002,01001,ERROR,ERROR,ERROR,ERROR,ERROR /* xyz{|}~ */
};
/* Bare bones 026 kepunch encodings */
static const int o26_ftn_code[] = {
ERROR,ERROR,ERROR,ERROR,ERROR,ERROR,ERROR,ERROR, /* control */
ERROR,ERROR,ERROR,ERROR,ERROR,ERROR,ERROR,ERROR, /* chars */
ERROR,ERROR,ERROR,ERROR,ERROR,ERROR,ERROR,ERROR, /* control */
ERROR,ERROR,ERROR,ERROR,ERROR,ERROR,ERROR,ERROR, /* chars */
00000,ERROR,ERROR,ERROR,02102,ERROR,ERROR,00042, /* !"#$%&' */
01042,04042,02042,04000,01102,02000,04102,01400, /* ()*+,-./ */
01000,00400,00200,00100,00040,00020,00010,00004, /* 01234567 */
00002,00001,ERROR,ERROR,ERROR,00102,ERROR,ERROR, /* 89:;<=>? */
ERROR,04400,04200,04100,04040,04020,04010,04004, /* @ABCDEFG */
04002,04001,02400,02200,02100,02040,02020,02010, /* HIJKLMNO */
02004,02002,02001,01200,01100,01040,01020,01010, /* PQRSTUVW */
01004,01002,01001,ERROR,ERROR,ERROR,ERROR,ERROR, /* XYZ[\]^_ */
ERROR,04400,04200,04100,04040,04020,04010,04004, /* `abcdefg */
04002,04001,02400,02200,02100,02040,02020,02010, /* hijklmno */
02004,02002,02001,01200,01100,01040,01020,01010, /* pqrstuvw */
01004,01002,01001,ERROR,ERROR,ERROR,ERROR,ERROR /* xyz{|}~ */
};
static const int o26_comm_code[] = {
ERROR,ERROR,ERROR,ERROR,ERROR,ERROR,ERROR,ERROR, /* control */
ERROR,ERROR,ERROR,ERROR,ERROR,ERROR,ERROR,ERROR, /* chars */
ERROR,ERROR,ERROR,ERROR,ERROR,ERROR,ERROR,ERROR, /* control */
ERROR,ERROR,ERROR,ERROR,ERROR,ERROR,ERROR,ERROR, /* chars */
00000,ERROR,ERROR,00102,02102,01042,04000,ERROR, /* !"#$%&' */
ERROR,ERROR,02042,ERROR,01102,02000,04102,01400, /* ()*+,-./ */
01000,00400,00200,00100,00040,00020,00010,00004, /* 01234567 */
00002,00001,ERROR,ERROR,04042,ERROR,ERROR,ERROR, /* 89:;<=>? */
00042,04400,04200,04100,04040,04020,04010,04004, /* @ABCDEFG */
04002,04001,02400,02200,02100,02040,02020,02010, /* HIJKLMNO */
02004,02002,02001,01200,01100,01040,01020,01010, /* PQRSTUVW */
01004,01002,01001,ERROR,ERROR,ERROR,ERROR,ERROR, /* XYZ[\]^_ */
ERROR,04400,04200,04100,04040,04020,04010,04004, /* `abcdefg */
04002,04001,02400,02200,02100,02040,02020,02010, /* hijklmno */
02004,02002,02001,01200,01100,01040,01020,01010, /* pqrstuvw */
01004,01002,01001,ERROR,ERROR,ERROR,ERROR,ERROR /* xyz{|}~ */
};
/* FULL EBCDIC, from Appendix C of System 360 Programming by Alex Thomas,
1977, Reinhart Press, San Francisco. Codes not in that table have been
left compatable with DEC's 029 table. Some control codes have been
left out */
static const int EBCDIC_code[] = {
05403,ERROR,ERROR,ERROR,ERROR,ERROR,ERROR,ERROR, /* control */
02011,04021,01021,ERROR,04041,02021,ERROR,ERROR, /* chars */
ERROR,ERROR,ERROR,ERROR,ERROR,ERROR,ERROR,ERROR, /* control */
ERROR,ERROR,ERROR,ERROR,01201,ERROR,ERROR,ERROR, /* chars */
00000,02202,00006,00102,02102,01042,04000,00022, /* !"#$%&' */
04022,02022,02042,04012,01102,02000,04102,01400, /* ()*+,-./ */
01000,00400,00200,00100,00040,00020,00010,00004, /* 01234567 */
00002,00001,00202,02012,04042,00012,01012,01006, /* 89:;<=>? */
00042,04400,04200,04100,04040,04020,04010,04004, /* @ABCDEFG */
04002,04001,02400,02200,02100,02040,02020,02010, /* HIJKLMNO */
02004,02002,02001,01200,01100,01040,01020,01010, /* PQRSTUVW */
01004,01002,01001,04202,02006,01202,04006,01022, /* XYZ[\]^_ */
ERROR,05400,05200,05100,05040,05020,05010,05004, /* `abcdefg */
05002,05001,06400,06200,06100,06040,06020,06010, /* hijklmno */
06004,06002,06001,03200,03100,03040,03020,03010, /* pqrstuvw */
03004,03002,03001,ERROR,ERROR,ERROR,ERROR,ERROR /* xyz{|}~ */
};
static const int h2c_code[4096] = {
0000, 0020, 0010, 0030, 0007, 0027, 0017, 0037,
0006, 0026, 0016, 0036, 0007, 0027, 0017, 0037,
0005, 0025, 0015, 0035, 0007, 0027, 0017, 0037,
0007, 0027, 0017, 0037, 0007, 0027, 0017, 0037,
0004, 0024, 0014, 0034, 0007, 0027, 0017, 0037,
0006, 0026, 0016, 0036, 0007, 0027, 0017, 0037,
0005, 0025, 0015, 0035, 0007, 0027, 0017, 0037,
0007, 0027, 0017, 0037, 0007, 0027, 0017, 0037,
0003, 0023, 0013, 0033, 0007, 0027, 0017, 0037,
0007, 0027, 0017, 0037, 0007, 0027, 0017, 0037,
0007, 0027, 0017, 0037, 0007, 0027, 0017, 0037,
0007, 0027, 0017, 0037, 0007, 0027, 0017, 0037,
0007, 0027, 0017, 0037, 0007, 0027, 0017, 0037,
0007, 0027, 0017, 0037, 0007, 0027, 0017, 0037,
0007, 0027, 0017, 0037, 0007, 0027, 0017, 0037,
0007, 0027, 0017, 0037, 0007, 0027, 0017, 0037,
0002, 0022, 0012, 0032, 0007, 0027, 0017, 0037,
0006, 0026, 0016, 0036, 0007, 0027, 0017, 0037,
0007, 0027, 0017, 0037, 0007, 0027, 0017, 0037,
0007, 0027, 0017, 0037, 0007, 0027, 0017, 0037,
0006, 0026, 0016, 0036, 0007, 0027, 0017, 0037,
0006, 0026, 0016, 0036, 0007, 0027, 0017, 0037,
0007, 0027, 0017, 0037, 0007, 0027, 0017, 0037,
0007, 0027, 0017, 0037, 0007, 0027, 0017, 0037,
0003, 0023, 0013, 0033, 0007, 0027, 0017, 0037,
0007, 0027, 0017, 0037, 0007, 0027, 0017, 0037,
0007, 0027, 0017, 0037, 0007, 0027, 0017, 0037,
0007, 0027, 0017, 0037, 0007, 0027, 0017, 0037,
0007, 0027, 0017, 0037, 0007, 0027, 0017, 0037,
0007, 0027, 0017, 0037, 0007, 0027, 0017, 0037,
0007, 0027, 0017, 0037, 0007, 0027, 0017, 0037,
0007, 0027, 0017, 0037, 0007, 0027, 0017, 0037,
0001, 0021, 0011, 0031, 0007, 0027, 0017, 0037,
0007, 0027, 0017, 0037, 0007, 0027, 0017, 0037,
0005, 0025, 0015, 0035, 0007, 0027, 0017, 0037,
0007, 0027, 0017, 0037, 0007, 0027, 0017, 0037,
0005, 0025, 0015, 0035, 0007, 0027, 0017, 0037,
0007, 0027, 0017, 0037, 0007, 0027, 0017, 0037,
0005, 0025, 0015, 0035, 0007, 0027, 0017, 0037,
0007, 0027, 0017, 0037, 0007, 0027, 0017, 0037,
0003, 0023, 0013, 0033, 0007, 0027, 0017, 0037,
0007, 0027, 0017, 0037, 0007, 0027, 0017, 0037,
0007, 0027, 0017, 0037, 0007, 0027, 0017, 0037,
0007, 0027, 0017, 0037, 0007, 0027, 0017, 0037,
0007, 0027, 0017, 0037, 0007, 0027, 0017, 0037,
0007, 0027, 0017, 0037, 0007, 0027, 0017, 0037,
0007, 0027, 0017, 0037, 0007, 0027, 0017, 0037,
0007, 0027, 0017, 0037, 0007, 0027, 0017, 0037,
0003, 0023, 0013, 0033, 0007, 0027, 0017, 0037,
0007, 0027, 0017, 0037, 0007, 0027, 0017, 0037,
0007, 0027, 0017, 0037, 0007, 0027, 0017, 0037,
0007, 0027, 0017, 0037, 0007, 0027, 0017, 0037,
0007, 0027, 0017, 0037, 0007, 0027, 0017, 0037,
0007, 0027, 0017, 0037, 0007, 0027, 0017, 0037,
0007, 0027, 0017, 0037, 0007, 0027, 0017, 0037,
0007, 0027, 0017, 0037, 0007, 0027, 0017, 0037,
0003, 0023, 0013, 0033, 0007, 0027, 0017, 0037,
0007, 0027, 0017, 0037, 0007, 0027, 0017, 0037,
0007, 0027, 0017, 0037, 0007, 0027, 0017, 0037,
0007, 0027, 0017, 0037, 0007, 0027, 0017, 0037,
0007, 0027, 0017, 0037, 0007, 0027, 0017, 0037,
0007, 0027, 0017, 0037, 0007, 0027, 0017, 0037,
0007, 0027, 0017, 0037, 0007, 0027, 0017, 0037,
0007, 0027, 0017, 0037, 0007, 0027, 0017, 0037,
0040, 0060, 0050, 0070, 0047, 0067, 0057, 0077,
0046, 0066, 0056, 0076, 0047, 0067, 0057, 0077,
0045, 0065, 0055, 0075, 0047, 0067, 0057, 0077,
0047, 0067, 0057, 0077, 0047, 0067, 0057, 0077,
0044, 0064, 0054, 0074, 0047, 0067, 0057, 0077,
0046, 0066, 0056, 0076, 0047, 0067, 0057, 0077,
0045, 0065, 0055, 0075, 0047, 0067, 0057, 0077,
0047, 0067, 0057, 0077, 0047, 0067, 0057, 0077,
0043, 0063, 0053, 0073, 0047, 0067, 0057, 0077,
0047, 0067, 0057, 0077, 0047, 0067, 0057, 0077,
0047, 0067, 0057, 0077, 0047, 0067, 0057, 0077,
0047, 0067, 0057, 0077, 0047, 0067, 0057, 0077,
0047, 0067, 0057, 0077, 0047, 0067, 0057, 0077,
0047, 0067, 0057, 0077, 0047, 0067, 0057, 0077,
0047, 0067, 0057, 0077, 0047, 0067, 0057, 0077,
0047, 0067, 0057, 0077, 0047, 0067, 0057, 0077,
0042, 0062, 0052, 0072, 0047, 0067, 0057, 0077,
0046, 0066, 0056, 0076, 0047, 0067, 0057, 0077,
0047, 0067, 0057, 0077, 0047, 0067, 0057, 0077,
0047, 0067, 0057, 0077, 0047, 0067, 0057, 0077,
0046, 0066, 0056, 0076, 0047, 0067, 0057, 0077,
0046, 0066, 0056, 0076, 0047, 0067, 0057, 0077,
0047, 0067, 0057, 0077, 0047, 0067, 0057, 0077,
0047, 0067, 0057, 0077, 0047, 0067, 0057, 0077,
0043, 0063, 0053, 0073, 0047, 0067, 0057, 0077,
0047, 0067, 0057, 0077, 0047, 0067, 0057, 0077,
0047, 0067, 0057, 0077, 0047, 0067, 0057, 0077,
0047, 0067, 0057, 0077, 0047, 0067, 0057, 0077,
0047, 0067, 0057, 0077, 0047, 0067, 0057, 0077,
0047, 0067, 0057, 0077, 0047, 0067, 0057, 0077,
0047, 0067, 0057, 0077, 0047, 0067, 0057, 0077,
0047, 0067, 0057, 0077, 0047, 0067, 0057, 0077,
0041, 0061, 0051, 0071, 0047, 0067, 0057, 0077,
0047, 0067, 0057, 0077, 0047, 0067, 0057, 0077,
0045, 0065, 0055, 0075, 0047, 0067, 0057, 0077,
0047, 0067, 0057, 0077, 0047, 0067, 0057, 0077,
0045, 0065, 0055, 0075, 0047, 0067, 0057, 0077,
0047, 0067, 0057, 0077, 0047, 0067, 0057, 0077,
0045, 0065, 0055, 0075, 0047, 0067, 0057, 0077,
0047, 0067, 0057, 0077, 0047, 0067, 0057, 0077,
0043, 0063, 0053, 0073, 0047, 0067, 0057, 0077,
0047, 0067, 0057, 0077, 0047, 0067, 0057, 0077,
0047, 0067, 0057, 0077, 0047, 0067, 0057, 0077,
0047, 0067, 0057, 0077, 0047, 0067, 0057, 0077,
0047, 0067, 0057, 0077, 0047, 0067, 0057, 0077,
0047, 0067, 0057, 0077, 0047, 0067, 0057, 0077,
0047, 0067, 0057, 0077, 0047, 0067, 0057, 0077,
0047, 0067, 0057, 0077, 0047, 0067, 0057, 0077,
0043, 0063, 0053, 0073, 0047, 0067, 0057, 0077,
0047, 0067, 0057, 0077, 0047, 0067, 0057, 0077,
0047, 0067, 0057, 0077, 0047, 0067, 0057, 0077,
0047, 0067, 0057, 0077, 0047, 0067, 0057, 0077,
0047, 0067, 0057, 0077, 0047, 0067, 0057, 0077,
0047, 0067, 0057, 0077, 0047, 0067, 0057, 0077,
0047, 0067, 0057, 0077, 0047, 0067, 0057, 0077,
0047, 0067, 0057, 0077, 0047, 0067, 0057, 0077,
0043, 0063, 0053, 0073, 0047, 0067, 0057, 0077,
0047, 0067, 0057, 0077, 0047, 0067, 0057, 0077,
0047, 0067, 0057, 0077, 0047, 0067, 0057, 0077,
0047, 0067, 0057, 0077, 0047, 0067, 0057, 0077,
0047, 0067, 0057, 0077, 0047, 0067, 0057, 0077,
0047, 0067, 0057, 0077, 0047, 0067, 0057, 0077,
0047, 0067, 0057, 0077, 0047, 0067, 0057, 0077,
0047, 0067, 0057, 0077, 0047, 0067, 0057, 0077,
0100, 0120, 0110, 0130, 0107, 0127, 0117, 0137,
0106, 0126, 0116, 0136, 0107, 0127, 0117, 0137,
0105, 0125, 0115, 0135, 0107, 0127, 0117, 0137,
0107, 0127, 0117, 0137, 0107, 0127, 0117, 0137,
0104, 0124, 0114, 0134, 0107, 0127, 0117, 0137,
0106, 0126, 0116, 0136, 0107, 0127, 0117, 0137,
0105, 0125, 0115, 0135, 0107, 0127, 0117, 0137,
0107, 0127, 0117, 0137, 0107, 0127, 0117, 0137,
0103, 0123, 0113, 0133, 0107, 0127, 0117, 0137,
0107, 0127, 0117, 0137, 0107, 0127, 0117, 0137,
0107, 0127, 0117, 0137, 0107, 0127, 0117, 0137,
0107, 0127, 0117, 0137, 0107, 0127, 0117, 0137,
0107, 0127, 0117, 0137, 0107, 0127, 0117, 0137,
0107, 0127, 0117, 0137, 0107, 0127, 0117, 0137,
0107, 0127, 0117, 0137, 0107, 0127, 0117, 0137,
0107, 0127, 0117, 0137, 0107, 0127, 0117, 0137,
0102, 0122, 0112, 0132, 0107, 0127, 0117, 0137,
0106, 0126, 0116, 0136, 0107, 0127, 0117, 0137,
0107, 0127, 0117, 0137, 0107, 0127, 0117, 0137,
0107, 0127, 0117, 0137, 0107, 0127, 0117, 0137,
0106, 0126, 0116, 0136, 0107, 0127, 0117, 0137,
0106, 0126, 0116, 0136, 0107, 0127, 0117, 0137,
0107, 0127, 0117, 0137, 0107, 0127, 0117, 0137,
0107, 0127, 0117, 0137, 0107, 0127, 0117, 0137,
0103, 0123, 0113, 0133, 0107, 0127, 0117, 0137,
0107, 0127, 0117, 0137, 0107, 0127, 0117, 0137,
0107, 0127, 0117, 0137, 0107, 0127, 0117, 0137,
0107, 0127, 0117, 0137, 0107, 0127, 0117, 0137,
0107, 0127, 0117, 0137, 0107, 0127, 0117, 0137,
0107, 0127, 0117, 0137, 0107, 0127, 0117, 0137,
0107, 0127, 0117, 0137, 0107, 0127, 0117, 0137,
0107, 0127, 0117, 0137, 0107, 0127, 0117, 0137,
0101, 0121, 0111, 0131, 0107, 0127, 0117, 0137,
0107, 0127, 0117, 0137, 0107, 0127, 0117, 0137,
0105, 0125, 0115, 0135, 0107, 0127, 0117, 0137,
0107, 0127, 0117, 0137, 0107, 0127, 0117, 0137,
0105, 0125, 0115, 0135, 0107, 0127, 0117, 0137,
0107, 0127, 0117, 0137, 0107, 0127, 0117, 0137,
0105, 0125, 0115, 0135, 0107, 0127, 0117, 0137,
0107, 0127, 0117, 0137, 0107, 0127, 0117, 0137,
0103, 0123, 0113, 0133, 0107, 0127, 0117, 0137,
0107, 0127, 0117, 0137, 0107, 0127, 0117, 0137,
0107, 0127, 0117, 0137, 0107, 0127, 0117, 0137,
0107, 0127, 0117, 0137, 0107, 0127, 0117, 0137,
0107, 0127, 0117, 0137, 0107, 0127, 0117, 0137,
0107, 0127, 0117, 0137, 0107, 0127, 0117, 0137,
0107, 0127, 0117, 0137, 0107, 0127, 0117, 0137,
0107, 0127, 0117, 0137, 0107, 0127, 0117, 0137,
0103, 0123, 0113, 0133, 0107, 0127, 0117, 0137,
0107, 0127, 0117, 0137, 0107, 0127, 0117, 0137,
0107, 0127, 0117, 0137, 0107, 0127, 0117, 0137,
0107, 0127, 0117, 0137, 0107, 0127, 0117, 0137,
0107, 0127, 0117, 0137, 0107, 0127, 0117, 0137,
0107, 0127, 0117, 0137, 0107, 0127, 0117, 0137,
0107, 0127, 0117, 0137, 0107, 0127, 0117, 0137,
0107, 0127, 0117, 0137, 0107, 0127, 0117, 0137,
0103, 0123, 0113, 0133, 0107, 0127, 0117, 0137,
0107, 0127, 0117, 0137, 0107, 0127, 0117, 0137,
0107, 0127, 0117, 0137, 0107, 0127, 0117, 0137,
0107, 0127, 0117, 0137, 0107, 0127, 0117, 0137,
0107, 0127, 0117, 0137, 0107, 0127, 0117, 0137,
0107, 0127, 0117, 0137, 0107, 0127, 0117, 0137,
0107, 0127, 0117, 0137, 0107, 0127, 0117, 0137,
0107, 0127, 0117, 0137, 0107, 0127, 0117, 0137,
0140, 0160, 0150, 0170, 0147, 0167, 0157, 0177,
0146, 0166, 0156, 0176, 0147, 0167, 0157, 0177,
0145, 0165, 0155, 0175, 0147, 0167, 0157, 0177,
0147, 0167, 0157, 0177, 0147, 0167, 0157, 0177,
0144, 0164, 0154, 0174, 0147, 0167, 0157, 0177,
0146, 0166, 0156, 0176, 0147, 0167, 0157, 0177,
0145, 0165, 0155, 0175, 0147, 0167, 0157, 0177,
0147, 0167, 0157, 0177, 0147, 0167, 0157, 0177,
0143, 0163, 0153, 0173, 0147, 0167, 0157, 0177,
0147, 0167, 0157, 0177, 0147, 0167, 0157, 0177,
0147, 0167, 0157, 0177, 0147, 0167, 0157, 0177,
0147, 0167, 0157, 0177, 0147, 0167, 0157, 0177,
0147, 0167, 0157, 0177, 0147, 0167, 0157, 0177,
0147, 0167, 0157, 0177, 0147, 0167, 0157, 0177,
0147, 0167, 0157, 0177, 0147, 0167, 0157, 0177,
0147, 0167, 0157, 0177, 0147, 0167, 0157, 0177,
0142, 0162, 0152, 0172, 0147, 0167, 0157, 0177,
0146, 0166, 0156, 0176, 0147, 0167, 0157, 0177,
0147, 0167, 0157, 0177, 0147, 0167, 0157, 0177,
0147, 0167, 0157, 0177, 0147, 0167, 0157, 0177,
0146, 0166, 0156, 0176, 0147, 0167, 0157, 0177,
0146, 0166, 0156, 0176, 0147, 0167, 0157, 0177,
0147, 0167, 0157, 0177, 0147, 0167, 0157, 0177,
0147, 0167, 0157, 0177, 0147, 0167, 0157, 0177,
0143, 0163, 0153, 0173, 0147, 0167, 0157, 0177,
0147, 0167, 0157, 0177, 0147, 0167, 0157, 0177,
0147, 0167, 0157, 0177, 0147, 0167, 0157, 0177,
0147, 0167, 0157, 0177, 0147, 0167, 0157, 0177,
0147, 0167, 0157, 0177, 0147, 0167, 0157, 0177,
0147, 0167, 0157, 0177, 0147, 0167, 0157, 0177,
0147, 0167, 0157, 0177, 0147, 0167, 0157, 0177,
0147, 0167, 0157, 0177, 0147, 0167, 0157, 0177,
0141, 0161, 0151, 0171, 0147, 0167, 0157, 0177,
0147, 0167, 0157, 0177, 0147, 0167, 0157, 0177,
0145, 0165, 0155, 0175, 0147, 0167, 0157, 0177,
0147, 0167, 0157, 0177, 0147, 0167, 0157, 0177,
0145, 0165, 0155, 0175, 0147, 0167, 0157, 0177,
0147, 0167, 0157, 0177, 0147, 0167, 0157, 0177,
0145, 0165, 0155, 0175, 0147, 0167, 0157, 0177,
0147, 0167, 0157, 0177, 0147, 0167, 0157, 0177,
0143, 0163, 0153, 0173, 0147, 0167, 0157, 0177,
0147, 0167, 0157, 0177, 0147, 0167, 0157, 0177,
0147, 0167, 0157, 0177, 0147, 0167, 0157, 0177,
0147, 0167, 0157, 0177, 0147, 0167, 0157, 0177,
0147, 0167, 0157, 0177, 0147, 0167, 0157, 0177,
0147, 0167, 0157, 0177, 0147, 0167, 0157, 0177,
0147, 0167, 0157, 0177, 0147, 0167, 0157, 0177,
0147, 0167, 0157, 0177, 0147, 0167, 0157, 0177,
0143, 0163, 0153, 0173, 0147, 0167, 0157, 0177,
0147, 0167, 0157, 0177, 0147, 0167, 0157, 0177,
0147, 0167, 0157, 0177, 0147, 0167, 0157, 0177,
0147, 0167, 0157, 0177, 0147, 0167, 0157, 0177,
0147, 0167, 0157, 0177, 0147, 0167, 0157, 0177,
0147, 0167, 0157, 0177, 0147, 0167, 0157, 0177,
0147, 0167, 0157, 0177, 0147, 0167, 0157, 0177,
0147, 0167, 0157, 0177, 0147, 0167, 0157, 0177,
0143, 0163, 0153, 0173, 0147, 0167, 0157, 0177,
0147, 0167, 0157, 0177, 0147, 0167, 0157, 0177,
0147, 0167, 0157, 0177, 0147, 0167, 0157, 0177,
0147, 0167, 0157, 0177, 0147, 0167, 0157, 0177,
0147, 0167, 0157, 0177, 0147, 0167, 0157, 0177,
0147, 0167, 0157, 0177, 0147, 0167, 0157, 0177,
0147, 0167, 0157, 0177, 0147, 0167, 0157, 0177,
0147, 0167, 0157, 0177, 0147, 0167, 0157, 0177,
0200, 0220, 0210, 0230, 0207, 0227, 0217, 0237,
0206, 0226, 0216, 0236, 0207, 0227, 0217, 0237,
0205, 0225, 0215, 0235, 0207, 0227, 0217, 0237,
0207, 0227, 0217, 0237, 0207, 0227, 0217, 0237,
0204, 0224, 0214, 0234, 0207, 0227, 0217, 0237,
0206, 0226, 0216, 0236, 0207, 0227, 0217, 0237,
0205, 0225, 0215, 0235, 0207, 0227, 0217, 0237,
0207, 0227, 0217, 0237, 0207, 0227, 0217, 0237,
0203, 0223, 0213, 0233, 0207, 0227, 0217, 0237,
0207, 0227, 0217, 0237, 0207, 0227, 0217, 0237,
0207, 0227, 0217, 0237, 0207, 0227, 0217, 0237,
0207, 0227, 0217, 0237, 0207, 0227, 0217, 0237,
0207, 0227, 0217, 0237, 0207, 0227, 0217, 0237,
0207, 0227, 0217, 0237, 0207, 0227, 0217, 0237,
0207, 0227, 0217, 0237, 0207, 0227, 0217, 0237,
0207, 0227, 0217, 0237, 0207, 0227, 0217, 0237,
0202, 0222, 0212, 0232, 0207, 0227, 0217, 0237,
0206, 0226, 0216, 0236, 0207, 0227, 0217, 0237,
0207, 0227, 0217, 0237, 0207, 0227, 0217, 0237,
0207, 0227, 0217, 0237, 0207, 0227, 0217, 0237,
0206, 0226, 0216, 0236, 0207, 0227, 0217, 0237,
0206, 0226, 0216, 0236, 0207, 0227, 0217, 0237,
0207, 0227, 0217, 0237, 0207, 0227, 0217, 0237,
0207, 0227, 0217, 0237, 0207, 0227, 0217, 0237,
0203, 0223, 0213, 0233, 0207, 0227, 0217, 0237,
0207, 0227, 0217, 0237, 0207, 0227, 0217, 0237,
0207, 0227, 0217, 0237, 0207, 0227, 0217, 0237,
0207, 0227, 0217, 0237, 0207, 0227, 0217, 0237,
0207, 0227, 0217, 0237, 0207, 0227, 0217, 0237,
0207, 0227, 0217, 0237, 0207, 0227, 0217, 0237,
0207, 0227, 0217, 0237, 0207, 0227, 0217, 0237,
0207, 0227, 0217, 0237, 0207, 0227, 0217, 0237,
0201, 0221, 0211, 0231, 0207, 0227, 0217, 0237,
0207, 0227, 0217, 0237, 0207, 0227, 0217, 0237,
0205, 0225, 0215, 0235, 0207, 0227, 0217, 0237,
0207, 0227, 0217, 0237, 0207, 0227, 0217, 0237,
0205, 0225, 0215, 0235, 0207, 0227, 0217, 0237,
0207, 0227, 0217, 0237, 0207, 0227, 0217, 0237,
0205, 0225, 0215, 0235, 0207, 0227, 0217, 0237,
0207, 0227, 0217, 0237, 0207, 0227, 0217, 0237,
0203, 0223, 0213, 0233, 0207, 0227, 0217, 0237,
0207, 0227, 0217, 0237, 0207, 0227, 0217, 0237,
0207, 0227, 0217, 0237, 0207, 0227, 0217, 0237,
0207, 0227, 0217, 0237, 0207, 0227, 0217, 0237,
0207, 0227, 0217, 0237, 0207, 0227, 0217, 0237,
0207, 0227, 0217, 0237, 0207, 0227, 0217, 0237,
0207, 0227, 0217, 0237, 0207, 0227, 0217, 0237,
0207, 0227, 0217, 0237, 0207, 0227, 0217, 0237,
0203, 0223, 0213, 0233, 0207, 0227, 0217, 0237,
0207, 0227, 0217, 0237, 0207, 0227, 0217, 0237,
0207, 0227, 0217, 0237, 0207, 0227, 0217, 0237,
0207, 0227, 0217, 0237, 0207, 0227, 0217, 0237,
0207, 0227, 0217, 0237, 0207, 0227, 0217, 0237,
0207, 0227, 0217, 0237, 0207, 0227, 0217, 0237,
0207, 0227, 0217, 0237, 0207, 0227, 0217, 0237,
0207, 0227, 0217, 0237, 0207, 0227, 0217, 0237,
0203, 0223, 0213, 0233, 0207, 0227, 0217, 0237,
0207, 0227, 0217, 0237, 0207, 0227, 0217, 0237,
0207, 0227, 0217, 0237, 0207, 0227, 0217, 0237,
0207, 0227, 0217, 0237, 0207, 0227, 0217, 0237,
0207, 0227, 0217, 0237, 0207, 0227, 0217, 0237,
0207, 0227, 0217, 0237, 0207, 0227, 0217, 0237,
0207, 0227, 0217, 0237, 0207, 0227, 0217, 0237,
0207, 0227, 0217, 0237, 0207, 0227, 0217, 0237,
0240, 0260, 0250, 0270, 0247, 0267, 0257, 0277,
0246, 0266, 0256, 0276, 0247, 0267, 0257, 0277,
0245, 0265, 0255, 0275, 0247, 0267, 0257, 0277,
0247, 0267, 0257, 0277, 0247, 0267, 0257, 0277,
0244, 0264, 0254, 0274, 0247, 0267, 0257, 0277,
0246, 0266, 0256, 0276, 0247, 0267, 0257, 0277,
0245, 0265, 0255, 0275, 0247, 0267, 0257, 0277,
0247, 0267, 0257, 0277, 0247, 0267, 0257, 0277,
0243, 0263, 0253, 0273, 0247, 0267, 0257, 0277,
0247, 0267, 0257, 0277, 0247, 0267, 0257, 0277,
0247, 0267, 0257, 0277, 0247, 0267, 0257, 0277,
0247, 0267, 0257, 0277, 0247, 0267, 0257, 0277,
0247, 0267, 0257, 0277, 0247, 0267, 0257, 0277,
0247, 0267, 0257, 0277, 0247, 0267, 0257, 0277,
0247, 0267, 0257, 0277, 0247, 0267, 0257, 0277,
0247, 0267, 0257, 0277, 0247, 0267, 0257, 0277,
0242, 0262, 0252, 0272, 0247, 0267, 0257, 0277,
0246, 0266, 0256, 0276, 0247, 0267, 0257, 0277,
0247, 0267, 0257, 0277, 0247, 0267, 0257, 0277,
0247, 0267, 0257, 0277, 0247, 0267, 0257, 0277,
0246, 0266, 0256, 0276, 0247, 0267, 0257, 0277,
0246, 0266, 0256, 0276, 0247, 0267, 0257, 0277,
0247, 0267, 0257, 0277, 0247, 0267, 0257, 0277,
0247, 0267, 0257, 0277, 0247, 0267, 0257, 0277,
0243, 0263, 0253, 0273, 0247, 0267, 0257, 0277,
0247, 0267, 0257, 0277, 0247, 0267, 0257, 0277,
0247, 0267, 0257, 0277, 0247, 0267, 0257, 0277,
0247, 0267, 0257, 0277, 0247, 0267, 0257, 0277,
0247, 0267, 0257, 0277, 0247, 0267, 0257, 0277,
0247, 0267, 0257, 0277, 0247, 0267, 0257, 0277,
0247, 0267, 0257, 0277, 0247, 0267, 0257, 0277,
0247, 0267, 0257, 0277, 0247, 0267, 0257, 0277,
0241, 0261, 0251, 0271, 0247, 0267, 0257, 0277,
0247, 0267, 0257, 0277, 0247, 0267, 0257, 0277,
0245, 0265, 0255, 0275, 0247, 0267, 0257, 0277,
0247, 0267, 0257, 0277, 0247, 0267, 0257, 0277,
0245, 0265, 0255, 0275, 0247, 0267, 0257, 0277,
0247, 0267, 0257, 0277, 0247, 0267, 0257, 0277,
0245, 0265, 0255, 0275, 0247, 0267, 0257, 0277,
0247, 0267, 0257, 0277, 0247, 0267, 0257, 0277,
0243, 0263, 0253, 0273, 0247, 0267, 0257, 0277,
0247, 0267, 0257, 0277, 0247, 0267, 0257, 0277,
0247, 0267, 0257, 0277, 0247, 0267, 0257, 0277,
0247, 0267, 0257, 0277, 0247, 0267, 0257, 0277,
0247, 0267, 0257, 0277, 0247, 0267, 0257, 0277,
0247, 0267, 0257, 0277, 0247, 0267, 0257, 0277,
0247, 0267, 0257, 0277, 0247, 0267, 0257, 0277,
0247, 0267, 0257, 0277, 0247, 0267, 0257, 0277,
0243, 0263, 0253, 0273, 0247, 0267, 0257, 0277,
0247, 0267, 0257, 0277, 0247, 0267, 0257, 0277,
0247, 0267, 0257, 0277, 0247, 0267, 0257, 0277,
0247, 0267, 0257, 0277, 0247, 0267, 0257, 0277,
0247, 0267, 0257, 0277, 0247, 0267, 0257, 0277,
0247, 0267, 0257, 0277, 0247, 0267, 0257, 0277,
0247, 0267, 0257, 0277, 0247, 0267, 0257, 0277,
0247, 0267, 0257, 0277, 0247, 0267, 0257, 0277,
0243, 0263, 0253, 0273, 0247, 0267, 0257, 0277,
0247, 0267, 0257, 0277, 0247, 0267, 0257, 0277,
0247, 0267, 0257, 0277, 0247, 0267, 0257, 0277,
0247, 0267, 0257, 0277, 0247, 0267, 0257, 0277,
0247, 0267, 0257, 0277, 0247, 0267, 0257, 0277,
0247, 0267, 0257, 0277, 0247, 0267, 0257, 0277,
0247, 0267, 0257, 0277, 0247, 0267, 0257, 0277,
0247, 0267, 0257, 0277, 0247, 0267, 0257, 0277,
0300, 0320, 0310, 0330, 0307, 0327, 0317, 0337,
0306, 0326, 0316, 0336, 0307, 0327, 0317, 0337,
0305, 0325, 0315, 0335, 0307, 0327, 0317, 0337,
0307, 0327, 0317, 0337, 0307, 0327, 0317, 0337,
0304, 0324, 0314, 0334, 0307, 0327, 0317, 0337,
0306, 0326, 0316, 0336, 0307, 0327, 0317, 0337,
0305, 0325, 0315, 0335, 0307, 0327, 0317, 0337,
0307, 0327, 0317, 0337, 0307, 0327, 0317, 0337,
0303, 0323, 0313, 0333, 0307, 0327, 0317, 0337,
0307, 0327, 0317, 0337, 0307, 0327, 0317, 0337,
0307, 0327, 0317, 0337, 0307, 0327, 0317, 0337,
0307, 0327, 0317, 0337, 0307, 0327, 0317, 0337,
0307, 0327, 0317, 0337, 0307, 0327, 0317, 0337,
0307, 0327, 0317, 0337, 0307, 0327, 0317, 0337,
0307, 0327, 0317, 0337, 0307, 0327, 0317, 0337,
0307, 0327, 0317, 0337, 0307, 0327, 0317, 0337,
0302, 0322, 0312, 0332, 0307, 0327, 0317, 0337,
0306, 0326, 0316, 0336, 0307, 0327, 0317, 0337,
0307, 0327, 0317, 0337, 0307, 0327, 0317, 0337,
0307, 0327, 0317, 0337, 0307, 0327, 0317, 0337,
0306, 0326, 0316, 0336, 0307, 0327, 0317, 0337,
0306, 0326, 0316, 0336, 0307, 0327, 0317, 0337,
0307, 0327, 0317, 0337, 0307, 0327, 0317, 0337,
0307, 0327, 0317, 0337, 0307, 0327, 0317, 0337,
0303, 0323, 0313, 0333, 0307, 0327, 0317, 0337,
0307, 0327, 0317, 0337, 0307, 0327, 0317, 0337,
0307, 0327, 0317, 0337, 0307, 0327, 0317, 0337,
0307, 0327, 0317, 0337, 0307, 0327, 0317, 0337,
0307, 0327, 0317, 0337, 0307, 0327, 0317, 0337,
0307, 0327, 0317, 0337, 0307, 0327, 0317, 0337,
0307, 0327, 0317, 0337, 0307, 0327, 0317, 0337,
0307, 0327, 0317, 0337, 0307, 0327, 0317, 0337,
0301, 0321, 0311, 0331, 0307, 0327, 0317, 0337,
0307, 0327, 0317, 0337, 0307, 0327, 0317, 0337,
0305, 0325, 0315, 0335, 0307, 0327, 0317, 0337,
0307, 0327, 0317, 0337, 0307, 0327, 0317, 0337,
0305, 0325, 0315, 0335, 0307, 0327, 0317, 0337,
0307, 0327, 0317, 0337, 0307, 0327, 0317, 0337,
0305, 0325, 0315, 0335, 0307, 0327, 0317, 0337,
0307, 0327, 0317, 0337, 0307, 0327, 0317, 0337,
0303, 0323, 0313, 0333, 0307, 0327, 0317, 0337,
0307, 0327, 0317, 0337, 0307, 0327, 0317, 0337,
0307, 0327, 0317, 0337, 0307, 0327, 0317, 0337,
0307, 0327, 0317, 0337, 0307, 0327, 0317, 0337,
0307, 0327, 0317, 0337, 0307, 0327, 0317, 0337,
0307, 0327, 0317, 0337, 0307, 0327, 0317, 0337,
0307, 0327, 0317, 0337, 0307, 0327, 0317, 0337,
0307, 0327, 0317, 0337, 0307, 0327, 0317, 0337,
0303, 0323, 0313, 0333, 0307, 0327, 0317, 0337,
0307, 0327, 0317, 0337, 0307, 0327, 0317, 0337,
0307, 0327, 0317, 0337, 0307, 0327, 0317, 0337,
0307, 0327, 0317, 0337, 0307, 0327, 0317, 0337,
0307, 0327, 0317, 0337, 0307, 0327, 0317, 0337,
0307, 0327, 0317, 0337, 0307, 0327, 0317, 0337,
0307, 0327, 0317, 0337, 0307, 0327, 0317, 0337,
0307, 0327, 0317, 0337, 0307, 0327, 0317, 0337,
0303, 0323, 0313, 0333, 0307, 0327, 0317, 0337,
0307, 0327, 0317, 0337, 0307, 0327, 0317, 0337,
0307, 0327, 0317, 0337, 0307, 0327, 0317, 0337,
0307, 0327, 0317, 0337, 0307, 0327, 0317, 0337,
0307, 0327, 0317, 0337, 0307, 0327, 0317, 0337,
0307, 0327, 0317, 0337, 0307, 0327, 0317, 0337,
0307, 0327, 0317, 0337, 0307, 0327, 0317, 0337,
0307, 0327, 0317, 0337, 0307, 0327, 0317, 0337,
0340, 0360, 0350, 0370, 0347, 0367, 0357, 0377,
0346, 0366, 0356, 0376, 0347, 0367, 0357, 0377,
0345, 0365, 0355, 0375, 0347, 0367, 0357, 0377,
0347, 0367, 0357, 0377, 0347, 0367, 0357, 0377,
0344, 0364, 0354, 0374, 0347, 0367, 0357, 0377,
0346, 0366, 0356, 0376, 0347, 0367, 0357, 0377,
0345, 0365, 0355, 0375, 0347, 0367, 0357, 0377,
0347, 0367, 0357, 0377, 0347, 0367, 0357, 0377,
0343, 0363, 0353, 0373, 0347, 0367, 0357, 0377,
0347, 0367, 0357, 0377, 0347, 0367, 0357, 0377,
0347, 0367, 0357, 0377, 0347, 0367, 0357, 0377,
0347, 0367, 0357, 0377, 0347, 0367, 0357, 0377,
0347, 0367, 0357, 0377, 0347, 0367, 0357, 0377,
0347, 0367, 0357, 0377, 0347, 0367, 0357, 0377,
0347, 0367, 0357, 0377, 0347, 0367, 0357, 0377,
0347, 0367, 0357, 0377, 0347, 0367, 0357, 0377,
0342, 0362, 0352, 0372, 0347, 0367, 0357, 0377,
0346, 0366, 0356, 0376, 0347, 0367, 0357, 0377,
0347, 0367, 0357, 0377, 0347, 0367, 0357, 0377,
0347, 0367, 0357, 0377, 0347, 0367, 0357, 0377,
0346, 0366, 0356, 0376, 0347, 0367, 0357, 0377,
0346, 0366, 0356, 0376, 0347, 0367, 0357, 0377,
0347, 0367, 0357, 0377, 0347, 0367, 0357, 0377,
0347, 0367, 0357, 0377, 0347, 0367, 0357, 0377,
0343, 0363, 0353, 0373, 0347, 0367, 0357, 0377,
0347, 0367, 0357, 0377, 0347, 0367, 0357, 0377,
0347, 0367, 0357, 0377, 0347, 0367, 0357, 0377,
0347, 0367, 0357, 0377, 0347, 0367, 0357, 0377,
0347, 0367, 0357, 0377, 0347, 0367, 0357, 0377,
0347, 0367, 0357, 0377, 0347, 0367, 0357, 0377,
0347, 0367, 0357, 0377, 0347, 0367, 0357, 0377,
0347, 0367, 0357, 0377, 0347, 0367, 0357, 0377,
0341, 0361, 0351, 0371, 0347, 0367, 0357, 0377,
0347, 0367, 0357, 0377, 0347, 0367, 0357, 0377,
0345, 0365, 0355, 0375, 0347, 0367, 0357, 0377,
0347, 0367, 0357, 0377, 0347, 0367, 0357, 0377,
0345, 0365, 0355, 0375, 0347, 0367, 0357, 0377,
0347, 0367, 0357, 0377, 0347, 0367, 0357, 0377,
0345, 0365, 0355, 0375, 0347, 0367, 0357, 0377,
0347, 0367, 0357, 0377, 0347, 0367, 0357, 0377,
0343, 0363, 0353, 0373, 0347, 0367, 0357, 0377,
0347, 0367, 0357, 0377, 0347, 0367, 0357, 0377,
0347, 0367, 0357, 0377, 0347, 0367, 0357, 0377,
0347, 0367, 0357, 0377, 0347, 0367, 0357, 0377,
0347, 0367, 0357, 0377, 0347, 0367, 0357, 0377,
0347, 0367, 0357, 0377, 0347, 0367, 0357, 0377,
0347, 0367, 0357, 0377, 0347, 0367, 0357, 0377,
0347, 0367, 0357, 0377, 0347, 0367, 0357, 0377,
0343, 0363, 0353, 0373, 0347, 0367, 0357, 0377,
0347, 0367, 0357, 0377, 0347, 0367, 0357, 0377,
0347, 0367, 0357, 0377, 0347, 0367, 0357, 0377,
0347, 0367, 0357, 0377, 0347, 0367, 0357, 0377,
0347, 0367, 0357, 0377, 0347, 0367, 0357, 0377,
0347, 0367, 0357, 0377, 0347, 0367, 0357, 0377,
0347, 0367, 0357, 0377, 0347, 0367, 0357, 0377,
0347, 0367, 0357, 0377, 0347, 0367, 0357, 0377,
0343, 0363, 0353, 0373, 0347, 0367, 0357, 0377,
0347, 0367, 0357, 0377, 0347, 0367, 0357, 0377,
0347, 0367, 0357, 0377, 0347, 0367, 0357, 0377,
0347, 0367, 0357, 0377, 0347, 0367, 0357, 0377,
0347, 0367, 0357, 0377, 0347, 0367, 0357, 0377,
0347, 0367, 0357, 0377, 0347, 0367, 0357, 0377,
0347, 0367, 0357, 0377, 0347, 0367, 0357, 0377,
0347, 0367, 0357, 0377, 0347, 0367, 0357, 0377,
};

View file

@ -1,6 +1,6 @@
/* pdp11_defs.h: PDP-11 simulator definitions /* pdp11_defs.h: PDP-11 simulator definitions
Copyright (c) 1993-2005, Robert M Supnik Copyright (c) 1993-2006, Robert M Supnik
Permission is hereby granted, free of charge, to any person obtaining a Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"), copy of this software and associated documentation files (the "Software"),
@ -26,6 +26,8 @@
The author gratefully acknowledges the help of Max Burnet, Megan Gentry, The author gratefully acknowledges the help of Max Burnet, Megan Gentry,
and John Wilson in resolving questions about the PDP-11 and John Wilson in resolving questions about the PDP-11
24-May-06 RMS Added 11/44 DR support (from CIS diagnostic)
17-May-06 RMS Added CR11/CD11 support (from John Dundas)
30-Sep-04 RMS Added Massbus support 30-Sep-04 RMS Added Massbus support
Removed Map_Addr prototype Removed Map_Addr prototype
Removed map argument from Unibus routines Removed map argument from Unibus routines
@ -162,7 +164,7 @@
/* Feature sets /* Feature sets
SDSD source addr, source fetch, dest addr, dest fetch SDSD source addr, dest addr, source fetch, dest fetch
SR switch register SR switch register
DR display register DR display register
RTT RTT instruction RTT RTT instruction
@ -195,7 +197,7 @@
#define HAS_SR (CPUT_04|CPUT_05|CPUT_20|CPUT_34|CPUT_40| \ #define HAS_SR (CPUT_04|CPUT_05|CPUT_20|CPUT_34|CPUT_40| \
CPUT_44|CPUT_45|CPUT_60|CPUT_70) CPUT_44|CPUT_45|CPUT_60|CPUT_70)
#define HAS_DR (CPUT_04|CPUT_05|CPUT_20|CPUT_24|CPUT_34| \ #define HAS_DR (CPUT_04|CPUT_05|CPUT_20|CPUT_24|CPUT_34| \
CPUT_40|CPUT_45|CPUT_60|CPUT_70) CPUT_40|CPUT_44|CPUT_45|CPUT_60|CPUT_70)
#define HAS_RTT (CPUT_03|CPUT_04|CPUT_F|CPUT_34|CPUT_40| \ #define HAS_RTT (CPUT_03|CPUT_04|CPUT_F|CPUT_34|CPUT_40| \
CPUT_44|CPUT_45|CPUT_60|CPUT_70|CPUT_J|CPUT_T) CPUT_44|CPUT_45|CPUT_60|CPUT_70|CPUT_J|CPUT_T)
#define HAS_SXS (CPUT_03|CPUT_F|CPUT_34|CPUT_40|CPUT_44| \ #define HAS_SXS (CPUT_03|CPUT_F|CPUT_34|CPUT_40|CPUT_44| \
@ -548,6 +550,8 @@ typedef struct pdp_dib DIB;
#define IOLN_XU 010 #define IOLN_XU 010
#define IOBA_RP (IOPAGEBASE + 016700) /* RP/RM */ #define IOBA_RP (IOPAGEBASE + 016700) /* RP/RM */
#define IOLN_RP 054 #define IOLN_RP 054
#define IOBA_CR (IOPAGEBASE + 017160) /* CD/CR/CM */
#define IOLN_CR 010
#define IOBA_RX (IOPAGEBASE + 017170) /* RX11 */ #define IOBA_RX (IOPAGEBASE + 017170) /* RX11 */
#define IOLN_RX 004 #define IOLN_RX 004
#define IOBA_RY (IOPAGEBASE + 017170) /* RY11 */ #define IOBA_RY (IOPAGEBASE + 017170) /* RY11 */
@ -628,7 +632,8 @@ typedef struct pdp_dib DIB;
#define INT_V_LPT 4 #define INT_V_LPT 4
#define INT_V_VHRX 5 #define INT_V_VHRX 5
#define INT_V_VHTX 6 #define INT_V_VHTX 6
#define INT_V_PIR4 7 #define INT_V_CR 7
#define INT_V_PIR4 8
#define INT_V_PIR3 0 /* BR3 */ #define INT_V_PIR3 0 /* BR3 */
#define INT_V_PIR2 0 /* BR2 */ #define INT_V_PIR2 0 /* BR2 */
@ -662,6 +667,7 @@ typedef struct pdp_dib DIB;
#define INT_LPT (1u << INT_V_LPT) #define INT_LPT (1u << INT_V_LPT)
#define INT_VHRX (1u << INT_V_VHRX) #define INT_VHRX (1u << INT_V_VHRX)
#define INT_VHTX (1u << INT_V_VHTX) #define INT_VHTX (1u << INT_V_VHTX)
#define INT_CR (1u << INT_V_CR)
#define INT_PIR4 (1u << INT_V_PIR4) #define INT_PIR4 (1u << INT_V_PIR4)
#define INT_PIR3 (1u << INT_V_PIR3) #define INT_PIR3 (1u << INT_V_PIR3)
#define INT_PIR2 (1u << INT_V_PIR2) #define INT_PIR2 (1u << INT_V_PIR2)
@ -692,6 +698,7 @@ typedef struct pdp_dib DIB;
#define IPL_LPT 4 #define IPL_LPT 4
#define IPL_VHRX 4 #define IPL_VHRX 4
#define IPL_VHTX 4 #define IPL_VHTX 4
#define IPL_CR 4
#define IPL_PIR7 7 #define IPL_PIR7 7
#define IPL_PIR6 6 #define IPL_PIR6 6
@ -722,6 +729,7 @@ typedef struct pdp_dib DIB;
#define VEC_TM 0224 #define VEC_TM 0224
#define VEC_TS 0224 #define VEC_TS 0224
#define VEC_TU 0224 #define VEC_TU 0224
#define VEC_CR 0230
#define VEC_RP 0254 #define VEC_RP 0254
#define VEC_TQ 0260 #define VEC_TQ 0260
#define VEC_RX 0264 #define VEC_RX 0264

File diff suppressed because it is too large Load diff

View file

@ -1,6 +1,6 @@
/* pdp11_ry.c: RX211/RXV21/RX02 floppy disk simulator /* pdp11_ry.c: RX211/RXV21/RX02 floppy disk simulator
Copyright (c) 1993-2005, Robert M Supnik Copyright (c) 1993-2006, Robert M Supnik
Permission is hereby granted, free of charge, to any person obtaining a Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"), copy of this software and associated documentation files (the "Software"),
@ -25,6 +25,7 @@
ry RX211/RXV21/RX02 floppy disk ry RX211/RXV21/RX02 floppy disk
15-May-06 RMS Fixed bug in autosize attach (reported by David Gesswein)
07-Jul-05 RMS Removed extraneous externs 07-Jul-05 RMS Removed extraneous externs
18-Feb-05 RMS Fixed bug in boot code (reported by Graham Toal) 18-Feb-05 RMS Fixed bug in boot code (reported by Graham Toal)
30-Sep-04 RMS Revised Unibus interface 30-Sep-04 RMS Revised Unibus interface
@ -569,16 +570,13 @@ return auto_config (0, 0); /* run autoconfig */
t_stat ry_attach (UNIT *uptr, char *cptr) t_stat ry_attach (UNIT *uptr, char *cptr)
{ {
uint32 sz; uint32 sz;
t_stat r;
r = attach_unit (uptr, cptr); if ((uptr->flags & UNIT_AUTO) && (sz = sim_fsize_name (cptr))) {
if (r != SCPE_OK) return r;
if ((uptr->flags & UNIT_AUTO) && (sz = sim_fsize (uptr->fileref))) {
if (sz > RX_SIZE) uptr->flags = uptr->flags | UNIT_DEN; if (sz > RX_SIZE) uptr->flags = uptr->flags | UNIT_DEN;
else uptr->flags = uptr->flags & ~UNIT_DEN; else uptr->flags = uptr->flags & ~UNIT_DEN;
} }
uptr->capac = (uptr->flags & UNIT_DEN)? RY_SIZE: RX_SIZE; uptr->capac = (uptr->flags & UNIT_DEN)? RY_SIZE: RX_SIZE;
return SCPE_OK; return attach_unit (uptr, cptr);
} }
/* Set size routine */ /* Set size routine */

View file

@ -1,6 +1,6 @@
/* pdp11_sys.c: PDP-11 simulator interface /* pdp11_sys.c: PDP-11 simulator interface
Copyright (c) 1993-2005, Robert M Supnik Copyright (c) 1993-2006, Robert M Supnik
Permission is hereby granted, free of charge, to any person obtaining a Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"), copy of this software and associated documentation files (the "Software"),
@ -23,6 +23,7 @@
used in advertising or otherwise to promote the sale, use or other dealings used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from Robert M Supnik. in this Software without prior written authorization from Robert M Supnik.
17-May-06 RMS Added CR11/CD11 support (from John Dundas)
16-Aug-05 RMS Fixed C++ declaration and cast problems 16-Aug-05 RMS Fixed C++ declaration and cast problems
22-Jul-05 RMS Fixed missing , in initializer (from Doug Gwyn) 22-Jul-05 RMS Fixed missing , in initializer (from Doug Gwyn)
22-Dec-03 RMS Added second DEUNA/DELUA support 22-Dec-03 RMS Added second DEUNA/DELUA support
@ -57,6 +58,7 @@ extern DEVICE cpu_dev, sys_dev;
extern DEVICE ptr_dev, ptp_dev; extern DEVICE ptr_dev, ptp_dev;
extern DEVICE tti_dev, tto_dev; extern DEVICE tti_dev, tto_dev;
extern DEVICE lpt_dev; extern DEVICE lpt_dev;
extern DEVICE cr_dev;
extern DEVICE clk_dev, pclk_dev; extern DEVICE clk_dev, pclk_dev;
extern DEVICE dz_dev; extern DEVICE dz_dev;
extern DEVICE vh_dev; extern DEVICE vh_dev;
@ -101,6 +103,7 @@ DEVICE *sim_devices[] = {
&ptp_dev, &ptp_dev,
&tti_dev, &tti_dev,
&tto_dev, &tto_dev,
&cr_dev,
&lpt_dev, &lpt_dev,
&clk_dev, &clk_dev,
&pclk_dev, &pclk_dev,

View file

@ -1,6 +1,6 @@
/* pdp11_tc.c: PDP-11 DECtape simulator /* pdp11_tc.c: PDP-11 DECtape simulator
Copyright (c) 1993-2005, Robert M Supnik Copyright (c) 1993-2006, Robert M Supnik
Permission is hereby granted, free of charge, to any person obtaining a Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"), copy of this software and associated documentation files (the "Software"),
@ -25,6 +25,7 @@
tc TC11/TU56 DECtape tc TC11/TU56 DECtape
10-Feb-06 RMS READ sets extended data bits in TCST (found by Alan Frisbie)
16-Aug-05 RMS Fixed C++ declaration and cast problems 16-Aug-05 RMS Fixed C++ declaration and cast problems
07-Jul-05 RMS Removed extraneous externs 07-Jul-05 RMS Removed extraneous externs
30-Sep-04 RMS Revised Unibus interface 30-Sep-04 RMS Revised Unibus interface
@ -866,6 +867,7 @@ switch (fnc) { /* at speed, check fnc *
ma = (CSR_GETMEX (tccm) << 16) | tcba; /* form 18b addr */ ma = (CSR_GETMEX (tccm) << 16) | tcba; /* form 18b addr */
ba = (blk * DTU_BSIZE (uptr)) + wrd; /* buffer ptr */ ba = (blk * DTU_BSIZE (uptr)) + wrd; /* buffer ptr */
tcdt = wbuf = fbuf[ba] & DMASK; /* read word */ tcdt = wbuf = fbuf[ba] & DMASK; /* read word */
tcst = (tcst & ~STA_M_XD) | ((fbuf[ma] >> 16) & STA_M_XD);
if (Map_WriteW (ma, 2, &wbuf)) { /* store, nxm? */ if (Map_WriteW (ma, 2, &wbuf)) { /* store, nxm? */
dt_seterr (uptr, STA_NXM); dt_seterr (uptr, STA_NXM);
break; break;

View file

@ -1,6 +1,6 @@
/* pdp11_tm.c: PDP-11 magnetic tape simulator /* pdp11_tm.c: PDP-11 magnetic tape simulator
Copyright (c) 1993-2005, Robert M Supnik Copyright (c) 1993-2006, Robert M Supnik
Permission is hereby granted, free of charge, to any person obtaining a Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"), copy of this software and associated documentation files (the "Software"),
@ -25,6 +25,7 @@
tm TM11/TU10 magtape tm TM11/TU10 magtape
16-Feb-06 RMS Added tape capacity checking
31-Oct-05 RMS Fixed address width for large files 31-Oct-05 RMS Fixed address width for large files
16-Aug-05 RMS Fixed C++ declaration and cast problems 16-Aug-05 RMS Fixed C++ declaration and cast problems
07-Jul-05 RMS Removed extraneous externs 07-Jul-05 RMS Removed extraneous externs
@ -129,7 +130,7 @@
#define STA_CRC 0020000 /* CRC error */ #define STA_CRC 0020000 /* CRC error */
#define STA_PAR 0010000 /* parity error */ #define STA_PAR 0010000 /* parity error */
#define STA_DLT 0004000 /* data late */ #define STA_DLT 0004000 /* data late */
#define STA_EOT 0002000 /* *end of tape */ #define STA_EOT 0002000 /* +end of tape */
#define STA_RLE 0001000 /* rec lnt error */ #define STA_RLE 0001000 /* rec lnt error */
#define STA_BAD 0000400 /* bad tape error */ #define STA_BAD 0000400 /* bad tape error */
#define STA_NXM 0000200 /* non-existent mem */ #define STA_NXM 0000200 /* non-existent mem */
@ -143,7 +144,7 @@
#define STA_CLR (STA_7TK | STA_SDN) /* always clear */ #define STA_CLR (STA_7TK | STA_SDN) /* always clear */
#define STA_DYN (STA_EOF | STA_EOT | STA_ONL | STA_BOT | \ #define STA_DYN (STA_EOF | STA_EOT | STA_ONL | STA_BOT | \
STA_WLK | STA_REW | STA_TUR) /* kept in USTAT */ STA_WLK | STA_REW | STA_TUR) /* dynamic */
#define STA_EFLGS (STA_ILL | STA_EOF | STA_CRC | STA_PAR | \ #define STA_EFLGS (STA_ILL | STA_EOF | STA_CRC | STA_PAR | \
STA_DLT | STA_EOT | STA_RLE | STA_BAD | STA_NXM) STA_DLT | STA_EOT | STA_RLE | STA_BAD | STA_NXM)
/* set error */ /* set error */
@ -230,6 +231,8 @@ MTAB tm_mod[] = {
{ MTUF_WLK, MTUF_WLK, "write locked", "LOCKED", &tm_vlock }, { MTUF_WLK, MTUF_WLK, "write locked", "LOCKED", &tm_vlock },
{ MTAB_XTD|MTAB_VUN, 0, "FORMAT", "FORMAT", { MTAB_XTD|MTAB_VUN, 0, "FORMAT", "FORMAT",
&sim_tape_set_fmt, &sim_tape_show_fmt, NULL }, &sim_tape_set_fmt, &sim_tape_show_fmt, NULL },
{ MTAB_XTD|MTAB_VUN, 0, "CAPACITY", "CAPACITY",
&sim_tape_set_capac, &sim_tape_show_capac, NULL },
{ MTAB_XTD|MTAB_VDV, 020, "ADDRESS", "ADDRESS", { MTAB_XTD|MTAB_VDV, 020, "ADDRESS", "ADDRESS",
&set_addr, &show_addr, NULL }, &set_addr, &show_addr, NULL },
{ MTAB_XTD|MTAB_VDV, 0, "VECTOR", "VECTOR", { MTAB_XTD|MTAB_VDV, 0, "VECTOR", "VECTOR",
@ -495,6 +498,7 @@ return r;
int32 tm_updcsta (UNIT *uptr) int32 tm_updcsta (UNIT *uptr)
{ {
tm_sta = (tm_sta & ~(STA_DYN | STA_CLR)) | (uptr->USTAT & STA_DYN); tm_sta = (tm_sta & ~(STA_DYN | STA_CLR)) | (uptr->USTAT & STA_DYN);
if (sim_tape_eot (uptr)) tm_sta = tm_sta | STA_EOT;
if (sim_is_active (uptr)) tm_sta = tm_sta & ~STA_TUR; if (sim_is_active (uptr)) tm_sta = tm_sta & ~STA_TUR;
else tm_sta = tm_sta | STA_TUR; else tm_sta = tm_sta | STA_TUR;
if (tm_sta & STA_EFLGS) tm_cmd = tm_cmd | MTC_ERR; if (tm_sta & STA_EFLGS) tm_cmd = tm_cmd | MTC_ERR;

View file

@ -1,6 +1,6 @@
/* pdp11_tq.c: TMSCP tape controller simulator /* pdp11_tq.c: TMSCP tape controller simulator
Copyright (c) 2002-2005, Robert M Supnik Copyright (c) 2002-2006, Robert M Supnik
Permission is hereby granted, free of charge, to any person obtaining a Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"), copy of this software and associated documentation files (the "Software"),
@ -25,6 +25,7 @@
tq TQK50 tape controller tq TQK50 tape controller
16-Feb-06 RMS Revised for new magtape capacity checking
31-Oct-05 RMS Fixed address width for large files 31-Oct-05 RMS Fixed address width for large files
16-Aug-05 RMS Fixed C++ declaration and cast problems 16-Aug-05 RMS Fixed C++ declaration and cast problems
22-Jul-05 RMS Fixed warning from Solaris C (from Doug Gwyn) 22-Jul-05 RMS Fixed warning from Solaris C (from Doug Gwyn)
@ -51,13 +52,16 @@
#include "vax_defs.h" #include "vax_defs.h"
#if (UNIBUS) #if (UNIBUS)
#define INIT_TYPE TQ8_TYPE #define INIT_TYPE TQ8_TYPE
#define INIT_CAP TQ8_CAP
#else #else
#define INIT_TYPE TQ5_TYPE #define INIT_TYPE TQ5_TYPE
#define INIT_CAP TQ5_CAP
#endif #endif
#else /* PDP-11 version */ #else /* PDP-11 version */
#include "pdp11_defs.h" #include "pdp11_defs.h"
#define INIT_TYPE TQ5_TYPE #define INIT_TYPE TQ5_TYPE
#define INIT_CAP TQ5_CAP
extern int32 cpu_opt; extern int32 cpu_opt;
#endif #endif
@ -192,7 +196,7 @@ struct tqpkt {
d##_CMOD, d##_MED, d##_FMT, d##_CAP, \ d##_CMOD, d##_MED, d##_FMT, d##_CAP, \
d##_UMOD, d##_CREV, d##_FREV, d##_UREV d##_UMOD, d##_CREV, d##_FREV, d##_UREV
#define TEST_EOT(u) (sim_tape_eot (u, drv_tab[tq_typ].cap)) #define TEST_EOT(u) (sim_tape_eot (u))
struct drvtyp { struct drvtyp {
uint32 uqpm; /* UQ port model */ uint32 uqpm; /* UQ port model */
@ -364,10 +368,10 @@ DIB tq_dib = {
}; };
UNIT tq_unit[] = { UNIT tq_unit[] = {
{ UDATA (&tq_svc, UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0), 0 }, { UDATA (&tq_svc, UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0), INIT_CAP },
{ UDATA (&tq_svc, UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0), 0 }, { UDATA (&tq_svc, UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0), INIT_CAP },
{ UDATA (&tq_svc, UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0), 0 }, { UDATA (&tq_svc, UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0), INIT_CAP },
{ UDATA (&tq_svc, UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0), 0 }, { UDATA (&tq_svc, UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0), INIT_CAP },
{ UDATA (&tq_tmrsvc, UNIT_DIS, 0) }, { UDATA (&tq_tmrsvc, UNIT_DIS, 0) },
{ UDATA (&tq_quesvc, UNIT_DIS, 0) } { UDATA (&tq_quesvc, UNIT_DIS, 0) }
}; };
@ -2155,14 +2159,15 @@ if (cptr) {
drv_tab[TQU_TYPE].cap = ((t_addr) cap) << 20; drv_tab[TQU_TYPE].cap = ((t_addr) cap) << 20;
} }
tq_typ = val; tq_typ = val;
for (i = 0; i < TQ_NUMDR; i++)
tq_unit[i].capac = drv_tab[tq_typ].cap;
return SCPE_OK; return SCPE_OK;
} }
/* Show controller type (and capacity for user-defined type) */ /* Show controller type and capacity */
t_stat tq_show_type (FILE *st, UNIT *uptr, int32 val, void *desc) t_stat tq_show_type (FILE *st, UNIT *uptr, int32 val, void *desc)
{ {
fprintf (st, "%s", drv_tab[tq_typ].name); fprintf (st, "%s (%dMB)", drv_tab[tq_typ].name, (uint32) (drv_tab[tq_typ].cap >> 20));
if (tq_typ == TQU_TYPE) fprintf (st, " (%dMB)", drv_tab[tq_typ].cap >> 20);
return SCPE_OK; return SCPE_OK;
} }

View file

@ -1,6 +1,6 @@
/* pdp11_ts.c: TS11/TSV05 magnetic tape simulator /* pdp11_ts.c: TS11/TSV05 magnetic tape simulator
Copyright (c) 1993-2005, Robert M Supnik Copyright (c) 1993-2006, Robert M Supnik
Permission is hereby granted, free of charge, to any person obtaining a Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"), copy of this software and associated documentation files (the "Software"),
@ -25,6 +25,7 @@
ts TS11/TSV05 magtape ts TS11/TSV05 magtape
16-Feb-06 RMS Added tape capacity checking
31-Oct-05 RMS Fixed address width for large files 31-Oct-05 RMS Fixed address width for large files
16-Aug-05 RMS Fixed C++ declaration and cast problems 16-Aug-05 RMS Fixed C++ declaration and cast problems
07-Jul-05 RMS Removed extraneous externs 07-Jul-05 RMS Removed extraneous externs
@ -346,6 +347,8 @@ MTAB ts_mod[] = {
{ MTUF_WLK, MTUF_WLK, "write locked", "LOCKED", NULL }, { MTUF_WLK, MTUF_WLK, "write locked", "LOCKED", NULL },
{ MTAB_XTD|MTAB_VUN, 0, "FORMAT", "FORMAT", { MTAB_XTD|MTAB_VUN, 0, "FORMAT", "FORMAT",
&sim_tape_set_fmt, &sim_tape_show_fmt, NULL }, &sim_tape_set_fmt, &sim_tape_show_fmt, NULL },
{ MTAB_XTD|MTAB_VUN, 0, "CAPACITY", "CAPACITY",
&sim_tape_set_capac, &sim_tape_show_capac, NULL },
{ MTAB_XTD|MTAB_VDV, 004, "ADDRESS", "ADDRESS", { MTAB_XTD|MTAB_VDV, 004, "ADDRESS", "ADDRESS",
&set_addr, &show_addr, NULL }, &set_addr, &show_addr, NULL },
{ MTAB_XTD|MTAB_VDV, 0, "VECTOR", "VECTOR", { MTAB_XTD|MTAB_VDV, 0, "VECTOR", "VECTOR",
@ -648,6 +651,8 @@ if (st = sim_tape_wrrecf (uptr, tsxb, fc)) /* write rec, err? */
return ts_map_status (st); /* return status */ return ts_map_status (st); /* return status */
msgxs0 = msgxs0 | XS0_MOT; /* tape has moved */ msgxs0 = msgxs0 | XS0_MOT; /* tape has moved */
msgrfc = 0; msgrfc = 0;
if (sim_tape_eot (&ts_unit)) /* EOT on write? */
return XTC (XS0_EOT, TC2);
return 0; return 0;
} }
@ -658,6 +663,8 @@ t_stat st;
if (st = sim_tape_wrtmk (uptr)) /* write tmk, err? */ if (st = sim_tape_wrtmk (uptr)) /* write tmk, err? */
return ts_map_status (st); /* return status */ return ts_map_status (st); /* return status */
msgxs0 = msgxs0 | XS0_MOT; /* tape has moved */ msgxs0 = msgxs0 | XS0_MOT; /* tape has moved */
if (sim_tape_eot (&ts_unit)) /* EOT on write? */
return XTC (XS0_EOT, TC2);
return XTC (XS0_TMK, TC0); return XTC (XS0_TMK, TC0);
} }
@ -783,7 +790,7 @@ switch (fnc) { /* case on func */
} }
return SCPE_OK; return SCPE_OK;
case FNC_CTL: /* control */ case FNC_CTL: /* control */
switch (mod) { /* case mode */ switch (mod) { /* case mode */
case 00: /* msg buf rls */ case 00: /* msg buf rls */
@ -903,7 +910,8 @@ switch (fnc) { /* case on func */
break; break;
case 04: /* rewind */ case 04: /* rewind */
if (!sim_tape_bot (uptr)) msgxs0 = msgxs0 | XS0_MOT; /* if tape moves */ if (!sim_tape_bot (uptr)) /* if tape moves */
msgxs0 = msgxs0 | XS0_MOT;
sim_tape_rewind (uptr); sim_tape_rewind (uptr);
break; break;
} }
@ -930,7 +938,10 @@ t = (t & ~(XS0_ONL | XS0_WLK | XS0_BOT | XS0_IE)) | XS0_PET;
if (ts_unit.flags & UNIT_ATT) { if (ts_unit.flags & UNIT_ATT) {
t = t | XS0_ONL; t = t | XS0_ONL;
if (sim_tape_wrp (&ts_unit)) t = t | XS0_WLK; if (sim_tape_wrp (&ts_unit)) t = t | XS0_WLK;
if (sim_tape_bot (&ts_unit)) t = (t | XS0_BOT) & ~XS0_EOT; if (sim_tape_bot (&ts_unit))
t = (t | XS0_BOT) & ~XS0_EOT;
if (sim_tape_eot (&ts_unit))
t = (t | XS0_EOT) & ~XS0_BOT;
} }
else t = t & ~XS0_EOT; else t = t & ~XS0_EOT;
if (cmdhdr & CMD_IE) t = t | XS0_IE; if (cmdhdr & CMD_IE) t = t | XS0_IE;

View file

@ -1,6 +1,6 @@
/* pdp11_tu.c - PDP-11 TM02/TU16 TM03/TU45/TU77 Massbus magnetic tape controller /* pdp11_tu.c - PDP-11 TM02/TU16 TM03/TU45/TU77 Massbus magnetic tape controller
Copyright (c) 1993-2005, Robert M Supnik Copyright (c) 1993-2006, Robert M Supnik
Permission is hereby granted, free of charge, to any person obtaining a Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"), copy of this software and associated documentation files (the "Software"),
@ -25,6 +25,7 @@
tu TM02/TM03 magtape tu TM02/TM03 magtape
16-Feb-06 RMS Added tape capacity checking
12-Nov-05 RMS Changed default formatter to TM03 (for VMS) 12-Nov-05 RMS Changed default formatter to TM03 (for VMS)
31-Oct-05 RMS Fixed address width for large files 31-Oct-05 RMS Fixed address width for large files
16-Aug-05 RMS Fixed C++ declaration and cast problems 16-Aug-05 RMS Fixed C++ declaration and cast problems
@ -308,6 +309,8 @@ MTAB tu_mod[] = {
{ UNIT_TYPE, UNIT_TU77, "TU77", "TU77", NULL }, { UNIT_TYPE, UNIT_TU77, "TU77", "TU77", NULL },
{ MTAB_XTD|MTAB_VUN, 0, "FORMAT", "FORMAT", { MTAB_XTD|MTAB_VUN, 0, "FORMAT", "FORMAT",
&sim_tape_set_fmt, &sim_tape_show_fmt, NULL }, &sim_tape_set_fmt, &sim_tape_show_fmt, NULL },
{ MTAB_XTD|MTAB_VUN, 0, "CAPACITY", "CAPACITY",
&sim_tape_set_capac, &sim_tape_show_capac, NULL },
{ 0 } { 0 }
}; };
@ -447,7 +450,7 @@ return SCPE_OK;
t_stat tu_go (int32 drv) t_stat tu_go (int32 drv)
{ {
int32 fnc, den, space_test = FS_BOT; int32 fnc, den;
UNIT *uptr; UNIT *uptr;
fnc = GET_FNC (tucs1); /* get function */ fnc = GET_FNC (tucs1); /* get function */
@ -511,13 +514,23 @@ switch (fnc) { /* case on function */
return SCPE_OK; return SCPE_OK;
case FNC_SPACEF: case FNC_SPACEF:
space_test = FS_EOT; if ((uptr->flags & UNIT_ATT) == 0) { /* unattached? */
tu_set_er (ER_UNS);
break;
}
if (sim_tape_eot (uptr) || ((tutc & TC_FCS) == 0)) {
tu_set_er (ER_NXF);
break;
}
uptr->USTAT = FS_PIP;
goto GO_XFER;
case FNC_SPACER: case FNC_SPACER:
if ((uptr->flags & UNIT_ATT) == 0) { /* unattached? */ if ((uptr->flags & UNIT_ATT) == 0) { /* unattached? */
tu_set_er (ER_UNS); tu_set_er (ER_UNS);
break; break;
} }
if ((tufs & space_test) || ((tutc & TC_FCS) == 0)) { if (sim_tape_bot (uptr) || ((tutc & TC_FCS) == 0)) {
tu_set_er (ER_NXF); tu_set_er (ER_NXF);
break; break;
} }
@ -623,7 +636,7 @@ switch (fnc) { /* case on function */
r = tu_map_err (drv, st, 0); /* map error */ r = tu_map_err (drv, st, 0); /* map error */
break; break;
} }
} while (tufc != 0); } while ((tufc != 0) && !sim_tape_eot (uptr));
if (tufc) tu_set_er (ER_FCE); if (tufc) tu_set_er (ER_FCE);
else tutc = tutc & ~TC_FCS; else tutc = tutc & ~TC_FCS;
break; break;
@ -786,7 +799,12 @@ if (tu_unit[drv].flags & UNIT_ATT) {
tufs = tufs | FS_MOL | tu_unit[drv].USTAT; tufs = tufs | FS_MOL | tu_unit[drv].USTAT;
if (tu_unit[drv].UDENS == TC_1600) tufs = tufs | FS_PE; if (tu_unit[drv].UDENS == TC_1600) tufs = tufs | FS_PE;
if (sim_tape_wrp (&tu_unit[drv])) tufs = tufs | FS_WRL; if (sim_tape_wrp (&tu_unit[drv])) tufs = tufs | FS_WRL;
if (sim_tape_bot (&tu_unit[drv]) && !act) tufs = tufs | FS_BOT; if (!act) {
if (sim_tape_bot (&tu_unit[drv]))
tufs = tufs | FS_BOT;
if (sim_tape_eot (&tu_unit[drv]))
tufs = tufs | FS_EOT;
}
} }
if (tuer) tufs = tufs | FS_ERR; if (tuer) tufs = tufs | FS_ERR;
if (tufs && !act) tufs = tufs | FS_RDY; if (tufs && !act) tufs = tufs | FS_RDY;

View file

@ -66,6 +66,7 @@
Modification history: Modification history:
27-Jan-06 RMS Fixed unaligned accesses in XQB (found by Doug Carman)
07-Jan-06 RMS Fixed unaligned access bugs (found by Doug Carman) 07-Jan-06 RMS Fixed unaligned access bugs (found by Doug Carman)
07-Sep-05 DTH Removed unused variable 07-Sep-05 DTH Removed unused variable
16-Aug-05 RMS Fixed C++ declaration and cast problems 16-Aug-05 RMS Fixed C++ declaration and cast problems
@ -306,16 +307,18 @@ UNIT xqb_unit[] = {
}; };
REG xqb_reg[] = { REG xqb_reg[] = {
{ GRDATA ( SA0, xqb.addr[0], XQ_RDX, 16, 0), REG_RO}, { GRDATA ( SA0, xqb.addr[0], XQ_RDX, 8, 0), REG_RO|REG_FIT},
{ GRDATA ( SA1, xqb.addr[1], XQ_RDX, 16, 0), REG_RO}, { GRDATA ( SA1, xqb.addr[1], XQ_RDX, 8, 0), REG_RO|REG_FIT},
{ GRDATA ( SA2, xqb.addr[2], XQ_RDX, 16, 0), REG_RO}, { GRDATA ( SA2, xqb.addr[2], XQ_RDX, 8, 0), REG_RO|REG_FIT},
{ GRDATA ( SA3, xqb.addr[3], XQ_RDX, 16, 0), REG_RO}, { GRDATA ( SA3, xqb.addr[3], XQ_RDX, 8, 0), REG_RO|REG_FIT},
{ GRDATA ( SA4, xqb.addr[4], XQ_RDX, 16, 0), REG_RO}, { GRDATA ( SA4, xqb.addr[4], XQ_RDX, 8, 0), REG_RO|REG_FIT},
{ GRDATA ( SA5, xqb.addr[5], XQ_RDX, 16, 0), REG_RO}, { GRDATA ( SA5, xqb.addr[5], XQ_RDX, 8, 0), REG_RO|REG_FIT},
{ GRDATA ( RBDL, xqb.rbdl, XQ_RDX, 32, 0) }, { GRDATA ( RBDL, xqb.rbdl[0], XQ_RDX, 16, 0), REG_FIT },
{ GRDATA ( XBDL, xqb.xbdl, XQ_RDX, 32, 0) }, { GRDATA ( RBDH, xqb.rbdl[1], XQ_RDX, 16, 0), REG_FIT },
{ GRDATA ( VAR, xqb.var, XQ_RDX, 16, 0) }, { GRDATA ( XBDL, xqb.xbdl[0], XQ_RDX, 16, 0), REG_FIT },
{ GRDATA ( CSR, xqb.csr, XQ_RDX, 16, 0) }, { GRDATA ( XBDH, xqb.xbdl[1], XQ_RDX, 16, 0), REG_FIT },
{ GRDATA ( VAR, xqb.var, XQ_RDX, 16, 0), REG_FIT },
{ GRDATA ( CSR, xqb.csr, XQ_RDX, 16, 0), REG_FIT },
{ FLDATA ( INT, xqb.irq, 0) }, { FLDATA ( INT, xqb.irq, 0) },
{ GRDATA ( SETUP_PRM, xqb.setup.promiscuous, XQ_RDX, 32, 0), REG_HRO}, { GRDATA ( SETUP_PRM, xqb.setup.promiscuous, XQ_RDX, 32, 0), REG_HRO},
{ GRDATA ( SETUP_MLT, xqb.setup.multicast, XQ_RDX, 32, 0), REG_HRO}, { GRDATA ( SETUP_MLT, xqb.setup.multicast, XQ_RDX, 32, 0), REG_HRO},

49
PDP11/txt2cbn.c Normal file
View file

@ -0,0 +1,49 @@
#include <stdio.h>
#define ERROR 00404
#include "pdp11_cr_dat.h"
static int colStart = 1; /* starting column */
static int colEnd = 80; /* ending column */
main ()
{
int col, c;
while (1) {
for (col = colStart; col <= colEnd; ) {
switch (c = fgetc (stdin)) {
case EOF:
/* fall through */
case '\n':
while (col <= colEnd) {
fputc (o29_code[' '] & 077, stdout);
fputc ((o29_code[' '] >> 6) & 077, stdout);
col++;
}
break;
case '\t':
do {
fputc (o29_code[' '] & 077, stdout);
fputc ((o29_code[' '] >> 6) & 077, stdout);
col++;
} while (((col & 07) != 1) && (col <= colEnd));
break;
default:
fputc (o29_code[c] & 077, stdout);
fputc ((o29_code[c] >> 6) & 077, stdout);
col++;
break;
}
}
/* flush long lines, or flag over-length card */
if (c != '\n' && c != EOF) {
printf ("overlength line\n");
do c = fgetc (stdin);
while ((c != EOF) && (c != '\n'));
}
if (c == EOF)
break;
}
exit (1);
}

File diff suppressed because it is too large Load diff

View file

@ -1,6 +1,6 @@
/* pdp18b_mt.c: 18b PDP magnetic tape simulator /* pdp18b_mt.c: 18b PDP magnetic tape simulator
Copyright (c) 1993-2005, Robert M Supnik Copyright (c) 1993-2006, Robert M Supnik
Permission is hereby granted, free of charge, to any person obtaining a Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"), copy of this software and associated documentation files (the "Software"),
@ -26,6 +26,7 @@
mt (PDP-9) TC59 magtape mt (PDP-9) TC59 magtape
(PDP-15) TC59D magtape (PDP-15) TC59D magtape
16-Feb-06 RMS Added tape capacity checking
16-Aug-05 RMS Fixed C++ declaration and cast problems 16-Aug-05 RMS Fixed C++ declaration and cast problems
18-Mar-05 RMS Added attached test to detach routine 18-Mar-05 RMS Added attached test to detach routine
14-Jan-04 RMS Revised IO device call interface 14-Jan-04 RMS Revised IO device call interface
@ -186,6 +187,8 @@ MTAB mt_mod[] = {
{ MTUF_WLK, MTUF_WLK, "write locked", "LOCKED", NULL }, { MTUF_WLK, MTUF_WLK, "write locked", "LOCKED", NULL },
{ MTAB_XTD|MTAB_VUN, 0, "FORMAT", "FORMAT", { MTAB_XTD|MTAB_VUN, 0, "FORMAT", "FORMAT",
&sim_tape_set_fmt, &sim_tape_show_fmt, NULL }, &sim_tape_set_fmt, &sim_tape_show_fmt, NULL },
{ MTAB_XTD|MTAB_VUN, 0, "CAPACITY", "CAPACITY",
&sim_tape_set_capac, &sim_tape_show_capac, NULL },
{ MTAB_XTD|MTAB_VDV, 0, "DEVNO", "DEVNO", { MTAB_XTD|MTAB_VDV, 0, "DEVNO", "DEVNO",
&set_devno, &show_devno, NULL }, &set_devno, &show_devno, NULL },
{ 0 } { 0 }
@ -263,6 +266,7 @@ t_stat mt_svc (UNIT *uptr)
int32 c, c1, c2, c3, f, i, p, u; int32 c, c1, c2, c3, f, i, p, u;
int32 wc, xma; int32 wc, xma;
t_mtrlnt tbc, cbc; t_mtrlnt tbc, cbc;
t_bool passed_eot;
t_stat st, r = SCPE_OK; t_stat st, r = SCPE_OK;
u = (int32) (uptr - mt_dev.units); /* get unit number */ u = (int32) (uptr - mt_dev.units); /* get unit number */
@ -283,6 +287,7 @@ if ((uptr->flags & UNIT_ATT) == 0) { /* if not attached */
return IORETURN (mt_stopioe, SCPE_UNATT); return IORETURN (mt_stopioe, SCPE_UNATT);
} }
passed_eot = sim_tape_eot (uptr); /* passed EOT? */
switch (f) { /* case on function */ switch (f) { /* case on function */
case FN_READ: /* read */ case FN_READ: /* read */
@ -362,7 +367,7 @@ switch (f) { /* case on function */
r = mt_map_err (uptr, st); /* map error */ r = mt_map_err (uptr, st); /* map error */
break; break;
} }
} while (M[MT_WC] != 0); } while ((M[MT_WC] != 0) && (passed_eot || !sim_tape_eot (uptr)));
break; break;
case FN_SPACER: /* space reverse */ case FN_SPACER: /* space reverse */
@ -376,6 +381,8 @@ switch (f) { /* case on function */
break; break;
} /* end case */ } /* end case */
if (!passed_eot && sim_tape_eot (uptr)) /* just passed EOT? */
uptr->USTAT = uptr->USTAT | STA_EOT;
mt_updcsta (uptr, STA_DON); /* set done */ mt_updcsta (uptr, STA_DON); /* set done */
if (mt_log) printf ("MT%d: fnc=%d done, ma=%o, wc=%o, sta=%o]\n", if (mt_log) printf ("MT%d: fnc=%d done, ma=%o, wc=%o, sta=%o]\n",
u, f, M[MT_CA], M[MT_WC], mt_sta); u, f, M[MT_CA], M[MT_WC], mt_sta);

View file

@ -1,6 +1,6 @@
/* pdp18b_rf.c: fixed head disk simulator /* pdp18b_rf.c: fixed head disk simulator
Copyright (c) 1993-2005, Robert M Supnik Copyright (c) 1993-2006, Robert M Supnik
Permission is hereby granted, free of charge, to any person obtaining a Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"), copy of this software and associated documentation files (the "Software"),
@ -26,6 +26,7 @@
rf (PDP-9) RF09/RF09 rf (PDP-9) RF09/RF09
(PDP-15) RF15/RS09 (PDP-15) RF15/RS09
15-May-06 RMS Fixed bug in autosize attach (reported by David Gesswein)
14-Jan-04 RMS Revised IO device call interface 14-Jan-04 RMS Revised IO device call interface
Changed sim_fsize calling sequence Changed sim_fsize calling sequence
26-Oct-03 RMS Cleaned up buffer copy code 26-Oct-03 RMS Cleaned up buffer copy code
@ -329,18 +330,15 @@ t_stat rf_attach (UNIT *uptr, char *cptr)
{ {
uint32 p, sz; uint32 p, sz;
uint32 ds_bytes = RF_DKSIZE * sizeof (int32); uint32 ds_bytes = RF_DKSIZE * sizeof (int32);
t_stat r;
r = attach_unit (uptr, cptr); if ((uptr->flags & UNIT_AUTO) && (sz = sim_fsize_name (cptr))) {
if (r != SCPE_OK) return r;
if ((uptr->flags & UNIT_AUTO) && (sz = sim_fsize (uptr->fileref))) {
p = (sz + ds_bytes - 1) / ds_bytes; p = (sz + ds_bytes - 1) / ds_bytes;
if (p >= RF_NUMDK) p = RF_NUMDK - 1; if (p >= RF_NUMDK) p = RF_NUMDK - 1;
uptr->flags = (uptr->flags & ~UNIT_PLAT) | uptr->flags = (uptr->flags & ~UNIT_PLAT) |
(p << UNIT_V_PLAT); (p << UNIT_V_PLAT);
} }
uptr->capac = UNIT_GETP (uptr->flags) * RF_DKSIZE; uptr->capac = UNIT_GETP (uptr->flags) * RF_DKSIZE;
return SCPE_OK; return attach_unit (uptr, cptr);
} }
/* Change disk size */ /* Change disk size */

View file

@ -25,6 +25,7 @@
df DF32 fixed head disk df DF32 fixed head disk
15-May-06 RMS Fixed bug in autosize attach (reported by Dave Gesswein)
07-Jan-06 RMS Fixed unaligned register access bug (found by Doug Carman) 07-Jan-06 RMS Fixed unaligned register access bug (found by Doug Carman)
04-Jan-04 RMS Changed sim_fsize calling sequence 04-Jan-04 RMS Changed sim_fsize calling sequence
26-Oct-03 RMS Cleaned up buffer copy code 26-Oct-03 RMS Cleaned up buffer copy code
@ -349,18 +350,15 @@ t_stat df_attach (UNIT *uptr, char *cptr)
{ {
uint32 p, sz; uint32 p, sz;
uint32 ds_bytes = DF_DKSIZE * sizeof (int16); uint32 ds_bytes = DF_DKSIZE * sizeof (int16);
t_stat r;
r = attach_unit (uptr, cptr); if ((uptr->flags & UNIT_AUTO) && (sz = sim_fsize_name (cptr))) {
if (r != SCPE_OK) return r;
if ((uptr->flags & UNIT_AUTO) && (sz = sim_fsize (uptr->fileref))) {
p = (sz + ds_bytes - 1) / ds_bytes; p = (sz + ds_bytes - 1) / ds_bytes;
if (p >= DF_NUMDK) p = DF_NUMDK - 1; if (p >= DF_NUMDK) p = DF_NUMDK - 1;
uptr->flags = (uptr->flags & ~UNIT_PLAT) | uptr->flags = (uptr->flags & ~UNIT_PLAT) |
(p << UNIT_V_PLAT); (p << UNIT_V_PLAT);
} }
uptr->capac = UNIT_GETP (uptr->flags) * DF_DKSIZE; uptr->capac = UNIT_GETP (uptr->flags) * DF_DKSIZE;
return SCPE_OK; return attach_unit (uptr, cptr);
} }
/* Change disk size */ /* Change disk size */

View file

@ -1,886 +0,0 @@
To: Users
From: Bob Supnik
Subj: PDP-8 Simulator Usage
Date: 01-Dec-2005
COPYRIGHT NOTICE
The following copyright notice applies to both the SIMH source and binary:
Original code published in 1993-2005, written by Robert M Supnik
Copyright (c) 1993-2005, Robert M Supnik
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Except as contained in this notice, the name of Robert M Supnik shall not be
used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from Robert M Supnik.
This memorandum documents the PDP-8 simulator.
1. Simulator Files
sim/ scp.h
sim_console.h
sim_defs.h
sim_fio.h
sim_rev.h
sim_sock.h
sim_tape.h
sim_timer.h
sim_tmxr.h
scp.c
sim_console.c
sim_fio.c
sim_sock.c
sim_tape.c
sim_timer.c
sim_tmxr.c
sim/pdp8/ pdp8_defs.h
pdp8_cpu.c
pdp8_df.c
pdp8_dt.c
pdp8_lp.c
pdp8_mt.c
pdp8_pt.c
pdp8_rf.c
pdp8_rk.c
pdp8_rl.c
pdp8_rx.c
pdp8_sys.c
pdp8_td.c
pdp8_tsc.c
pdp8_tt.c
pdp8_ttx.c
2. PDP-8 Features
The PDP-8 simulator is configured as follows:
device simulates
name(s)
CPU PDP-8/E CPU with 4KW-32KW of memory
- KE8E extended arithmetic element (EAE)
- KM8E memory management and timeshare control
TSC TSC8-75 ETOS operating system timeshare control
PTR,PTP PC8E paper tape reader/punch
TTI,TTO KL8E console terminal
TTIX,TTOX KL8JA additional terminals
LPT LE8E line printer
CLK DK8E line frequency clock (also PDP-8/A compatible)
RK RK8E/RK05 cartridge disk controller with four drives
RF RF08/RS08 fixed head disk controller with 1-4 platters, or
DF DF32/DS32 fixed head disk controller with 1-4 platters
RL RL8A/RL01 cartridge disk controller with four drives
RX RX8E/RX01, RX28/RX02 floppy disk controller with two drives
DT TC08/TU56 DECtape controller with eight drives
TD TD8E/TU56 DECtape controller with two drives
MT TM8E/TU10 magnetic tape controller with eight drives
Most devices can be disabled or enabled, by the commands:
SET <dev> DISABLED
SET <dev> ENABLED
The simulator allows most device numbers to be changed, by the command:
SET <dev> DEV=<number>
The PDP-8 can support only one of the set {DF32, RF08, RL8A} using the
default device numbers, since they all use device numbers 60-61. The
default is the RF08. To change the disk at device numbers 60-61:
sim> SET RF DISABLED disable RF08
sim> SET DF ENABLED, or enable DF32
sim> SET RL ENABLED enable RL8A
The PDP-8 can only support one of the set {TC08, TD8E} using the default
device numbers, since both use device number 77. The default is the
TC08. To change the DECtape controller to the TD8E:
sim> SET DT DISABLED disable TC08
sim> SET TD ENABLED enable TD8E
Alternately, the device conflict can be eliminated by changing device
numbers:
sim> SET RL DEV=50
sim> SET RL ENA
sim> SET TD DEV=74
sim> SET TD ENA
However, devices can only be BOOTed with their default device numbers.
The PDP-8 simulator implements several unique stop conditions:
- if an undefined instruction (unimplemented IOT or OPR) is
decoded, and register STOP_INST
- if a simulated DECtape runs off the end of its reel
The PDP-8 loader supports both RIM format and BIN format tapes. If the file
extension is .RIM, or the -r switch is specified with LOAD, the file is
assumed to be RIM format; if the file extension is not .RIM, or if the -b
switch is specified, the file is assumed to be BIN format.
2.1 CPU
The only CPU options are the presence of the EAE and the size of main
memory; the memory extension and time-share control is always included,
even if memory size is 4K.
SET CPU EAE enable EAE
SET CPU NOEAE disable EAE
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
If memory size is being reduced, and the memory being truncated contains
non-zero data, the simulator asks for confirmation. Data in the truncated
portion of memory is lost. Initial memory size is 32K.
CPU registers include the visible state of the processor as well as the
control registers for the interrupt system.
name size comments
PC 15 program counter, including IF as high 3 bits
AC 12 accumulator
MQ 12 multiplier-quotient
L 1 link
SR 12 front panel switches
IF 3 instruction field
DF 3 data field
IB 3 instruction field buffer
SF 7 save field
UF 1 user mode flag
UB 1 user mode buffer
SC 5 EAE shift counter
GTF 1 EAE greater than flag
EMODE 1 EAE mode (0 = A, 1 = B)
ION 1 interrupt enable
ION_DELAY 1 interrupt enable delay for ION
CIF_DELAY 1 interrupt enable delay for CIF
PWR_INT 1 power fail interrupt
UF_INT 1 user mode violation interrupt
INT 15 interrupt pending flags
DONE 15 device done flags
ENABLE 15 device interrupt enable flags
PCQ[0:63] 15 PC prior to last JMP, JMS, or interrupt;
most recent PC change first
STOP_INST 1 stop on undefined instruction
WRU 8 interrupt character
The CPU can maintain a history of the most recently executed instructions.
This is controlled by the SET CPU HISTORY and SHOW CPU HISTORY commands:
SET CPU HISTORY clear history buffer
SET CPU HISTORY=0 disable history
SET CPU HISTORY=n enable history, length = n
SHOW CPU HISTORY print CPU history
SHOW CPU HISTORY=n print first n entries of CPU history
The maximum length for the history is 65536 entries.
2.2 TSC8-75 ETOS Timeshare Control (TSC)
ETOS is a timeshared operating system for the PDP-8, providing multiple
virtual OS/8 environments for up to 32 users. It requires a special
timeshare control option, the TSC8-75. The TSC8-75 is normally disabled;
to run ETOS, it must be enabled with the command:
SET TSC ENABLED
The TSC8-75 implements these registers:
IR most recently trapped instruction
PC PC of most recently trapped instruction
CDF 1 if trapped instruction is CDF, 0 otherwise
ENB interrupt enable flag
INT interrupt pending flag
Except for operation of ETOS, the TSC8-75 should be left disabled.
2.3 Programmed I/O Devices
2.3.1 PC8E Paper Tape Reader (PTR)
The paper tape reader (PTR) reads data from a disk file. The POS
register specifies the number of the next data item to be read. Thus,
by changing POS, the user can backspace or advance the reader.
The paper tape reader supports the BOOT command. BOOT PTR copies the
RIM loader into memory and starts it running.
The paper tape reader implements these registers:
name size comments
BUF 8 last data item processed
DONE 1 device done flag
ENABLE 1 interrupt enable flag
INT 1 interrupt pending flag
POS 32 position in the input file
TIME 24 time from I/O initiation to interrupt
STOP_IOE 1 stop on I/O error
Error handling is as follows:
error STOP_IOE processed as
not attached 1 report error and stop
0 out of tape
end of file 1 report error and stop
0 out of tape
OS I/O error x report error and stop
2.3.2 PC8E Paper Tape Punch (PTP)
The paper tape punch (PTP) writes data to a disk file. The POS register
specifies the number of the next data item to bewritten. Thus, by
changing POS, the user can backspace or advance the punch.
The paper tape punch implements these registers:
name size comments
BUF 8 last data item processed
DONE 1 device done flag
ENABLE 1 interrupt enable flag
INT 1 interrupt pending flag
POS 32 position in the output file
TIME 24 time from I/O initiation to interrupt
STOP_IOE 1 stop on I/O error
Error handling is as follows:
error STOP_IOE processed as
not attached 1 report error and stop
0 out of tape
OS I/O error x report error and stop
2.3.3 KL8E Terminal Input (TTI)
The terminal interfaces (TTI, TTO) can be set to one of four modes,
KSR, 7B, 7B, or 8B:
mode input characters output characters
KSR lower case converted lower case converted
to upper case, to upper case,
high-order bit set high-order bit cleared,
non-printing characters
suppressed
7P high-order bit cleared high-order bit cleared,
non-printing characters
suppressed
7B high-order bit cleared high-order bit cleared
8B no changes no changes
The default mode is KSR.
The terminal input (TTI) polls the console keyboard for input. It
implements these registers:
name size comments
BUF 8 last data item processed
DONE 1 device done flag
ENABLE 1 interrupt enable flag
INT 1 interrupt pending flag
POS 32 number of characters input
TIME 24 keyboard polling interval
2.3.4 KL8E Terminal Output (TTO)
The terminal output (TTO) writes to the simulator console window. It
implements these registers:
name size comments
BUF 8 last data item processed
DONE 1 device done flag
ENABLE 1 interrupt enable flag
INT 1 interrupt pending flag
POS 32 number of characters output
TIME 24 time from I/O initiation to interrupt
2.3.5 LE8E Line Printer (LPT)
The line printer (LPT) writes data to a disk file. The POS register
specifies the number of the next data item to be read or written. Thus,
by changing POS, the user can backspace or advance the printer.
The line printer implements these registers:
name size comments
BUF 8 last data item processed
ERR 1 error status flag
DONE 1 device done flag
ENABLE 1 interrupt enable flag
INT 1 interrupt pending flag
POS 32 position in the output file
TIME 24 time from I/O initiation to interrupt
Error handling is as follows:
error STOP_IOE processed as
not attached 1 report error and stop
0 set error flag
OS I/O error x report error and stop
2.3.6 DK8E Line-Frequency Clock (CLK)
The real-time clock (CLK) frequency can be adjusted as follows:
SET CLK 60HZ set frequency to 60Hz
SET CLK 50HZ set frequency to 50Hz
The default is 60Hz.
The clock implements these registers:
name size comments
DONE 1 device done flag
ENABLE 1 interrupt enable flag
INT 1 interrupt pending flag
TIME 24 clock interval
The real-time clock autocalibrates; the clock interval is adjusted up or
down so that the clock tracks actual elapsed time.
2.3.7 KL8JA Additional Terminals (TTIX, TTOX)
The additional terminals consist of two independent devices, TTIX and
TTOX. The entire set is modelled as a terminal multiplexor, with TTIX
as the master unit. The additional terminals perform input and output
through Telnet sessions connected to a user-specified port. The ATTACH
command specifies the port to be used:
ATTACH TTIX <port> set up listening port
where port is a decimal number between 1 and 65535 that is not being used
for other TCP/IP activities.
The additional terminals can be set to one of four modes: UC, 7P, 7B,
or 8B.
mode input characters output characters
UC lower case converted lower case converted
to upper case, to upper case,
high-order bit cleared high-order bit cleared,
non-printing characters
suppressed
7P high-order bit cleared high-order bit cleared,
non-printing characters
suppressed
7B high-order bit cleared high-order bit cleared
8B no changes no changes
The default mode is UC. Finally, each line supports output logging.
The SET TTOXn LOG command enables logging on a line:
SET TTOXn LOG=filename log output of line n to filename
The SET TTOXLn NOLOG command disables logging and closes the open log
file, if any.
Once TTIX is attached and the simulator is running, the terminals listen
for connections on the specified port. They assume that the incoming
connections are Telnet connections. The connections remain open until
disconnected either by the Telnet client, a SET TTIX DISCONNECT command,
or a DETACH TTIX command.
The SHOW TTIX CONNECTIONS command displays the current connections to the
extra terminals. The SHOW TTIX STATISTICS command displays statistics for
active connections. The SET TTIXn DISCONNECT command disconnects line n.
The input device (TTIX) implements these registers:
name size comments
BUF[0:3] 8 input buffer, lines 0-3
DONE 4 device done flags (line 0 rightmost)
ENABLE 4 interrupt enable flag
INT 4 interrupt pending flag
TIME 24 initial polling interval
TPS 10 polls per second after calibration
The output device (TTOX) implements these registers:
name size comments
BUF[0:3] 8 last data item processed, lines 0-3
DONE 4 device done flag (line 0 rightmost)
ENABLE 4 interrupt enable flag
INT 4 interrupt pending flag
TIME[0:3] 24 time from I/O initiation to interrupt,
lines 0-3
The additional terminals do not support save and restore. All open
connections are lost when the simulator shuts down or TTIX is detached.
2.3.8 TD8E/TU56 DECtape (TD)
The TD8E is a programmed I/O, non-interrupt controller, supporting two
DECtape drives (0 and 1). The TD8E simulator puts a high burden on the
host processor, because tape activity is simulated a line (3b) at a time.
Unless the PDP-8 software requires the TD8E, the TC08 should be used
to simulate DECtapes. The TD8E is disabled by default.
TD8E options include the ability to make units write enabled or write
locked.
SET DTn LOCKED set unit n write locked
SET DTn WRITEENABLED set unit n write enabled
Units can also be set ENABLED or DISABLED. The TD8E supports the BOOT
command, but only for unit 0.
The TD8E supports supports PDP-8 format, PDP-11 format, and 18b format
DECtape images. ATTACH tries to determine the tape format from the DECtape
image; the user can force a particular format with switches:
-r PDP-8 format
-s PDP-11 format
-t 18b format
The TD8E controller is a data-only simulator; the timing and mark
track, and block header and trailer, are not stored. Thus, read always
produces standard values for header and trailer words, and write throws
header and trailer words into the bit bucket.
The TD8E controller implements these registers:
name size comments
TDCMD 4 command register
TDDAT 12 data register
TDMTK 6 mark track register
TDSLF 1 single line flag
TDQLF 1 quad line flag
TDTME 1 timing error flag
TDQL 2 quad line counter
LTIME 31 time between lines
DCTIME 31 time to decelerate to a full stop
POS[0:7] 32 position, in lines, units 0-7
STATT[0:7] 18 unit state, units 0-7
STOP_OFFR 1 stop on off-reel error
The LTIME parameter should not be changed, or OS/8 may fail to run
correctly. The DCTIME parameter should always be at least 100 times
greater than LTIME. Acceleration time is 75% of deceleration time.
2.4 Moving Head Disks
2.4.1 RK8E Cartridge Disk (RK)
RK8E options include the ability to make units write enabled or write locked:
SET RKn LOCKED set unit n write locked
SET RKn WRITEENABLED set unit n write enabled
Units can also be set ENABLED or DISABLED. The RK8E supports the BOOT command.
The RK8E implements these registers:
name size comments
RKSTA 12 status
RKCMD 12 disk command
RKDA 12 disk address
RKMA 12 current memory address
BUSY 1 control busy flag
INT 1 interrupt pending flag
STIME 24 seek time, per cylinder
RTIME 24 rotational delay
STOP_IOE 1 stop on I/O error
Error handling is as follows:
error STOP_IOE processed as
not attached 1 report error and stop
0 disk not ready
end of file x assume rest of disk is zero
OS I/O error x report error and stop
2.4.2 RL8A Cartridge Disk (RL)
RL8A options include the ability to make units write enabled or write locked:
SET RLn LOCKED set unit n write locked
SET RLn WRITEENABLED set unit n write enabled
Units can also be set ENABLED or DISABLED. The RL8A supports the BOOT command,
but only for unit 0.
The RL8A implements these registers:
name size comments
RLCSA 12 control/status A
RLCSB 12 control/status B
RLMA 12 memory address
RLWC 12 word count
RLSA 6 sector address
RLER 12 error flags
RLSI 16 silo top word
RLSI1 16 silo second word
RLSI2 16 silo third word
RLSIL 1 silo read left/right flag
INT 1 interrupt request
DONE 1 done flag
ERR 1 composite error flag
STIME 1 seek time, per cylinder
RTIME 1 rotational delay
STOP_IOE 1 stop on I/O error
Error handling is as follows:
error STOP_IOE processed as
not attached 1 report error and stop
0 disk not ready
end of file x assume rest of disk is zero
OS I/O error x report error and stop
2.5 RX8E/RX01, RX28/RX02 Floppy Disk (RX)
The RX can be configured as an RX8E with two RX01 drives, or an RX28 with
two RX02 drives:
SET RX RX8E set controller to RX8E/RX01
SET RX RX28 set controller to RX28/RX02
The controller is set to the RX8E by default. The RX28 is not backwards-
compatible with the RX8E and will not work with the standard OS/8 V3D floppy
disk driver.
RX8E options include the ability to set units write enabled or write locked:
SET RXn LOCKED set unit n write locked
SET RXn WRITEENABLED set unit n write enabled
RX28 options include, in addition, the ability to set the unit density to
single density, double density, or autosized; autosizing is the default:
SET RXn SINGLE set unit n single density
SET RXn DOUBLE set unit n double density
SET RXn AUTOSIZE set unit n autosize
The RX8E and RX28 support the BOOT command.
The RX8E and RX28 implement these registers:
name size comments
RXCS 12 status
RXDB 12 data buffer
RXES 12 error status
RXTA 8 current track
RXSA 8 current sector
STAPTR 4 controller state
BUFPTR 8 buffer pointer
INT 1 interrupt pending flag
DONE 1 device done flag
ENABLE 1 interrupt enable flag
TR 1 transfer ready flag
ERR 1 error flag
CTIME 24 command completion time
STIME 24 seek time, per track
XTIME 24 transfer ready delay
STOP_IOE 1 stop on I/O error
SBUF[0:255] 8 sector buffer array
Error handling is as follows:
error STOP_IOE processed as
not attached 1 report error and stop
0 disk not ready
RX01 and RX02 data files are buffered in memory; therefore, end of file
and OS I/O errors cannot occur.
2.6 Fixed Head Disks
Either the RF08 or the DF32 can be present in a configuration, but
not both, with default device addressing.
2.6.1 RF08/RS08 Fixed Head Disk (RF)
RF08 options include the ability to set the number of platters to a
fixed value between 1 and 4, or to autosize the number of platters
from the attached file:
SET RF 1P one platter (256K)
SET RF 2P two platters (512K)
SET RF 3P three platters (768K)
SET RF 4P four platters (1024K)
SET RF AUTOSIZE autosized on attach
The default is one platter.
The RF08 implements these registers:
name size comments
STA 12 status
DA 20 current disk address
MA 12 memory address (in memory)
WC 12 word count (in memory)
WLK 32 write lock switches
INT 1 interrupt pending flag
DONE 1 device done flag
TIME 24 rotational delay, per word
BURST 1 burst flag
STOP_IOE 1 stop on I/O error
The RF08 supports the BOOT command. The default bootstrap is for OS/8. To
bootstrap the 4K Disk Monitor, use the BOOT -D RF command.
The RF08 is a three-cycle data break device. If BURST = 0, word transfers
are scheduled individually; if BURST = 1, the entire transfer occurs in
a single data break.
Error handling is as follows:
error STOP_IOE processed as
not attached 1 report error and stop
0 disk not ready
RF08 data files are buffered in memory; therefore, end of file and OS
I/O errors cannot occur.
2.6.2 DF32/DS32 Fixed Head Disk (RF)
DF32 options include the ability to set the number of platters to a
fixed value between 1 and 4, or to autosize the number of platters
from the attached file:
SET DF 1P one platter (32K)
SET DF 2P two platters (64K)
SET DF 3P three platters (98K)
SET DF 4P four platters (128K)
SET DF AUTOSIZE autosized on attach
The default is one platter.
The DF32 implements these registers:
name size comments
STA 12 status, disk and memory address extension
DA 12 low order disk address
MA 12 memory address (in memory)
WC 12 word count (in memory)
WLK 16 write lock switches
INT 1 interrupt pending flag
DONE 1 device done flag
TIME 24 rotational delay, per word
BURST 1 burst flag
STOP_IOE 1 stop on I/O error
The DF32 supports the BOOT command. The default bootstrap is for OS/8. To
bootstrap the 4K Disk Monitor, use the BOOT -D DF command.
The DF32 is a three-cycle data break device. If BURST = 0, word transfers
are scheduled individually; if BURST = 1, the entire transfer occurs in
a single data break.
Error handling is as follows:
error STOP_IOE processed as
not attached 1 report error and stop
0 disk not ready
DF32 data files are buffered in memory; therefore, end of file and OS
I/O errors cannot occur.
2.7 TC08/TU56 DECtape (DT)
DECtapes drives are numbered 1-8; in the simulator, drive 8 is unit 0.
TC08 options include the ability to make units write enabled or write
locked.
SET DTn LOCKED set unit n write locked
SET DTn WRITEENABLED set unit n write enabled
Units can also be set ENABLED or DISABLED. The TC08 supports the BOOT
command, but only for unit 0.
The TC08 supports supports PDP-8 format, PDP-11 format, and 18b format
DECtape images. ATTACH tries to determine the tape format from the DECtape
image; the user can force a particular format with switches:
-r PDP-8 format
-s PDP-11 format
-t 18b format
The TC08 controller is a data-only simulator; the timing and mark
track, and block header and trailer, are not stored. Thus, the WRITE
TIMING AND MARK TRACK function is not supported; the READ ALL function
always returns the hardware standard block header and trailer; and the
WRITE ALL function dumps non-data words into the bit bucket.
The DECtape controller implements these registers:
name size comments
DTSA 12 status register A
DTSB 12 status register B
INT 1 interrupt pending flag
ENB 1 interrupt enable flag
DTF 1 DECtape flag
ERF 1 error flag
CA 12 current address (memory location 7754)
WC 12 word count (memory location 7755)
LTIME 31 time between lines
DCTIME 31 time to decelerate to a full stop
SUBSTATE 2 read/write command substate
POS[0:7] 32 position, in lines, units 0-7
STATT[0:7] 31 unit state, units 0-7
STOP_OFFR 1 stop on off-reel error
It is critically important to maintain certain timing relationships
among the DECtape parameters, or the DECtape simulator will fail to
operate correctly.
- LTIME must be at least 6
- DCTIME needs to be at least 100 times LTIME
Acceleration time is set to 75% of deceleration time.
2.8 TM8E Magnetic Tape (MT)
Magnetic tape options include the ability to make units write enabled or
or write locked.
SET MTn LOCKED set unit n write locked
SET MTn WRITEENABLED set unit n write enabled
Units can also be set ENABLED or DISABLED.
The magnetic tape controller implements these registers:
name size comments
CMD 12 command
FNC 12 function
CA 12 memory address
WC 12 word count
DB 12 data buffer
STA 12 main status
STA2 6 secondary status
DONE 1 device done flag
INT 1 interrupt pending flag
STOP_IOE 1 stop on I/O error
TIME 24 record delay
UST[0:7] 24 unit status, units 0-7
POS[0:7] 32 position, units 0-7
Error handling is as follows:
error processed as
not attached tape not ready; if STOP_IOE, stop
end of file bad tape
OS I/O error parity error; if STOP_IOE, stop
2.9 Symbolic Display and Input
The PDP-8 simulator implements symbolic display and input. Display is
controlled by command line switches:
-a display as ASCII character
-c display as (sixbit) character string
-t display as (TSS/8 sixbit) character string
-m display instruction mnemonics
Input parsing is controlled by the first character typed in or by command
line switches:
' or -a ASCII character
" or -c two character sixbit string
# or -t two character TSS/8 sixbit string
alphabetic instruction mnemonic
numeric octal number
Instruction input uses standard PDP-8 assembler syntax. There are four
instruction classes: memory reference, IOT, field change, and operate.
Memory reference instructions have the format
memref {I} {C/Z} address
where I signifies indirect, C a current page reference, and Z a zero page
reference. The address is an octal number in the range 0 - 07777; if C or
Z is specified, the address is a page offset in the range 0 - 177. Normally,
C is not needed; the simulator figures out from the address what mode to use.
However, when referencing memory outside the CPU (eg, disks), there is no
valid PC, and C must be used to specify current page addressing.
IOT instructions consist of single mnemonics, eg, KRB, TLS. IOT instructions
may be or'd together
iot iot iot...
The simulator does not check the legality of the proposed combination. IOT's
for which there is no opcode may be specified as IOT n, where n is an octal
number in the range 0 - 0777.
Field change instructions (CIF, CDF) have the format
fldchg field
where field is an octal number in the range 0 - 7. Field change instructions
may be or'd together.
Operate instructions have the format
opr opr opr...
The simulator does not check the legality of the proposed combination. EAE
mode A and B mnemonics may be specified regardless of the EAE mode. The
operands for MUY and DVI must be deposited explicitly.

View file

@ -1,6 +1,6 @@
/* pdp8_mt.c: PDP-8 magnetic tape simulator /* pdp8_mt.c: PDP-8 magnetic tape simulator
Copyright (c) 1993-2005, Robert M Supnik Copyright (c) 1993-2006, Robert M Supnik
Permission is hereby granted, free of charge, to any person obtaining a Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"), copy of this software and associated documentation files (the "Software"),
@ -25,6 +25,7 @@
mt TM8E/TU10 magtape mt TM8E/TU10 magtape
16-Feb-06 RMS Added tape capacity checking
16-Aug-05 RMS Fixed C++ declaration and cast problems 16-Aug-05 RMS Fixed C++ declaration and cast problems
18-Mar-05 RMS Added attached test to detach routine 18-Mar-05 RMS Added attached test to detach routine
25-Apr-03 RMS Revised for extended file support 25-Apr-03 RMS Revised for extended file support
@ -204,6 +205,8 @@ MTAB mt_mod[] = {
{ MTUF_WLK, MTUF_WLK, "write locked", "LOCKED", &mt_vlock }, { MTUF_WLK, MTUF_WLK, "write locked", "LOCKED", &mt_vlock },
{ MTAB_XTD|MTAB_VUN, 0, "FORMAT", "FORMAT", { MTAB_XTD|MTAB_VUN, 0, "FORMAT", "FORMAT",
&sim_tape_set_fmt, &sim_tape_show_fmt, NULL }, &sim_tape_set_fmt, &sim_tape_show_fmt, NULL },
{ MTAB_XTD|MTAB_VUN, 0, "CAPACITY", "CAPACITY",
&sim_tape_set_capac, &sim_tape_show_capac, NULL },
{ MTAB_XTD|MTAB_VDV, 0, "DEVNO", "DEVNO", { MTAB_XTD|MTAB_VDV, 0, "DEVNO", "DEVNO",
&set_dev, &show_dev, NULL }, &set_dev, &show_dev, NULL },
{ 0 } { 0 }
@ -369,6 +372,7 @@ t_stat mt_svc (UNIT *uptr)
{ {
int32 f, i, p, u, wc, xma; int32 f, i, p, u, wc, xma;
t_mtrlnt tbc, cbc; t_mtrlnt tbc, cbc;
t_bool passed_eot;
uint16 c, c1, c2; uint16 c, c1, c2;
t_stat st, r = SCPE_OK; t_stat st, r = SCPE_OK;
@ -397,6 +401,7 @@ if ((uptr->flags & UNIT_ATT) == 0) { /* if not attached */
return IORETURN (mt_stopioe, SCPE_UNATT); return IORETURN (mt_stopioe, SCPE_UNATT);
} }
passed_eot = sim_tape_eot (uptr); /* passed eot? */
switch (f) { /* case on function */ switch (f) { /* case on function */
case FN_READ: /* read */ case FN_READ: /* read */
@ -460,7 +465,7 @@ switch (f) { /* case on function */
r = mt_map_err (uptr, st); /* map error */ r = mt_map_err (uptr, st); /* map error */
break; /* stop */ break; /* stop */
} }
} while (mt_wc != 0); } while ((mt_wc != 0) && (passed_eot || !sim_tape_eot (uptr)));
break; break;
case FN_SPACER: /* space reverse */ case FN_SPACER: /* space reverse */
@ -474,6 +479,8 @@ switch (f) { /* case on function */
break; break;
} /* end case */ } /* end case */
if (!passed_eot && sim_tape_eot (uptr)) /* just passed EOT? */
uptr->USTAT = uptr->USTAT | STA_EOT;
mt_cu = (mt_cu & ~CU_EMA) | ((xma >> (12 - CU_V_EMA)) & CU_EMA); mt_cu = (mt_cu & ~CU_EMA) | ((xma >> (12 - CU_V_EMA)) & CU_EMA);
mt_ca = xma & 07777; /* update mem addr */ mt_ca = xma & 07777; /* update mem addr */
mt_set_done (); /* set done */ mt_set_done (); /* set done */

View file

@ -25,6 +25,7 @@
rf RF08 fixed head disk rf RF08 fixed head disk
15-May-06 RMS Fixed bug in autosize attach (reported by Dave Gesswein)
07-Jan-06 RMS Fixed unaligned register access bug (found by Doug Carman) 07-Jan-06 RMS Fixed unaligned register access bug (found by Doug Carman)
04-Jan-04 RMS Changed sim_fsize calling sequence 04-Jan-04 RMS Changed sim_fsize calling sequence
26-Oct-03 RMS Cleaned up buffer copy code 26-Oct-03 RMS Cleaned up buffer copy code
@ -413,18 +414,15 @@ t_stat rf_attach (UNIT *uptr, char *cptr)
{ {
uint32 sz, p; uint32 sz, p;
uint32 ds_bytes = RF_DKSIZE * sizeof (int16); uint32 ds_bytes = RF_DKSIZE * sizeof (int16);
t_stat r;
r = attach_unit (uptr, cptr); if ((uptr->flags & UNIT_AUTO) && (sz = sim_fsize_name (cptr))) {
if (r != SCPE_OK) return r;
if ((uptr->flags & UNIT_AUTO) && (sz = sim_fsize (uptr->fileref))) {
p = (sz + ds_bytes - 1) / ds_bytes; p = (sz + ds_bytes - 1) / ds_bytes;
if (p >= RF_NUMDK) p = RF_NUMDK - 1; if (p >= RF_NUMDK) p = RF_NUMDK - 1;
uptr->flags = (uptr->flags & ~UNIT_PLAT) | uptr->flags = (uptr->flags & ~UNIT_PLAT) |
(p << UNIT_V_PLAT); (p << UNIT_V_PLAT);
} }
uptr->capac = UNIT_GETP (uptr->flags) * RF_DKSIZE; uptr->capac = UNIT_GETP (uptr->flags) * RF_DKSIZE;
return SCPE_OK; return attach_unit (uptr, cptr);
} }
/* Change disk size */ /* Change disk size */

View file

@ -1,6 +1,6 @@
/* pdp8_rx.c: RX8E/RX01, RX28/RX02 floppy disk simulator /* pdp8_rx.c: RX8E/RX01, RX28/RX02 floppy disk simulator
Copyright (c) 1993-2005, Robert M Supnik Copyright (c) 1993-2006, Robert M Supnik
Permission is hereby granted, free of charge, to any person obtaining a Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"), copy of this software and associated documentation files (the "Software"),
@ -25,6 +25,7 @@
rx RX8E/RX01, RX28/RX02 floppy disk rx RX8E/RX01, RX28/RX02 floppy disk
15-May-06 RMS Fixed bug in autosize attach (reported by Dave Gesswein)
04-Jan-04 RMS Changed sim_fsize calling sequence 04-Jan-04 RMS Changed sim_fsize calling sequence
05-Nov-03 RMS Fixed bug in RX28 read status (found by Charles Dickman) 05-Nov-03 RMS Fixed bug in RX28 read status (found by Charles Dickman)
26-Oct-03 RMS Cleaned up buffer copy code, fixed double density write 26-Oct-03 RMS Cleaned up buffer copy code, fixed double density write
@ -579,16 +580,13 @@ return SCPE_OK;
t_stat rx_attach (UNIT *uptr, char *cptr) t_stat rx_attach (UNIT *uptr, char *cptr)
{ {
uint32 sz; uint32 sz;
t_stat r;
r = attach_unit (uptr, cptr); if ((uptr->flags & UNIT_AUTO) && (sz = sim_fsize_name (cptr))) {
if (r != SCPE_OK) return r;
if ((uptr->flags & UNIT_AUTO) && (sz = sim_fsize (uptr->fileref))) {
if (sz > RX_SIZE) uptr->flags = uptr->flags | UNIT_DEN; if (sz > RX_SIZE) uptr->flags = uptr->flags | UNIT_DEN;
else uptr->flags = uptr->flags & ~UNIT_DEN; else uptr->flags = uptr->flags & ~UNIT_DEN;
} }
uptr->capac = (uptr->flags & UNIT_DEN)? RX2_SIZE: RX_SIZE; uptr->capac = (uptr->flags & UNIT_DEN)? RX2_SIZE: RX_SIZE;
return SCPE_OK; return attach_unit (uptr, cptr);
} }
/* Set size routine */ /* Set size routine */
@ -613,9 +611,9 @@ for (i = 0; i < RX_NUMDR; i++) {
if (rx_unit[i].flags & UNIT_ATT) return SCPE_ALATT; if (rx_unit[i].flags & UNIT_ATT) return SCPE_ALATT;
} }
for (i = 0; i < RX_NUMDR; i++) { for (i = 0; i < RX_NUMDR; i++) {
rx_unit[i].flags = rx_unit[i].flags & ~(UNIT_DEN | UNIT_AUTO); if (val) rx_unit[i].flags = rx_unit[i].flags | UNIT_DEN | UNIT_AUTO;
rx_unit[i].capac = RX_SIZE; else rx_unit[i].flags = rx_unit[i].flags & ~(UNIT_DEN | UNIT_AUTO);
if (val) rx_unit[i].flags = rx_unit[i].flags | UNIT_AUTO; rx_unit[i].capac = val? RX2_SIZE: RX_SIZE;
} }
rx_28 = val; rx_28 = val;
return SCPE_OK; return SCPE_OK;

View file

@ -1,559 +0,0 @@
To: Users
From: Bob Supnik
Subj: SDS 940 Simulator Usage
Date: 01-Jul-2005
COPYRIGHT NOTICE
The following copyright notice applies to both the SIMH source and binary:
Original code published in 1993-2005, written by Robert M Supnik
Copyright (c) 1993-2005, Robert M Supnik
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Except as contained in this notice, the name of Robert M Supnik shall not be
used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from Robert M Supnik.
This memorandum documents the SDS 940 simulator.
1. Simulator Files
sim/ scp.h
sim_console.h
sim_defs.h
sim_fio.h
sim_rev.h
sim_sock.h
sim_tape.h
sim_timer.h
sim_tmxr.h
scp.c
sim_console.c
sim_fio.c
sim_sock.c
sim_tape.c
sim_timer.c
sim_tmxr.c
sim/sds/ sds_defs.h
sds_cpu.c
sds_drm.c
sds_dsk.c
sds_io.c
sds_lp.c
sds_mt.c
sds_mux.c
sds_rad.c
sds_stddev.c
sds_sys.c
2. SDS 940 Features
The SDS-940 simulator is configured as follows:
device simulates
name(s)
CPU SDS-940 CPU with 16KW to 64KW of memory
CHAN I/O channels
PTR paper tape reader
PTP paper tape punch
TTI console input
TTO console output
LPT line printer
RTC real-time clock
MUX terminal multiplexor
DRM Project Genie drum
RAD fixed head disk
DSK 9164/9165 rapid access (moving head) disk
MT magnetic tape
Most devices can be disabled or enabled with the SET <dev> DISABLED and
SET <dev> ENABLED commands, respectively.
2.1 CPU
The CPU options set the size of main memory and the configuration of
peripherals.
SET CPU 16K set memory size = 16KW
SET CPU 32K set memory size = 32KW
SET CPU 48K set memory size = 48KW
SET CPU 64K set memory size = 64KW
SET CPU GENIE enable DRM, set terminal mux
to GENIE mode
SET CPU SDS disable DRM, set terminal mux
to SDS mode
If memory size is being reduced, and the memory being truncated contains
non-zero data, the simulator asks for confirmation. Data in the truncated
portion of memory is lost. Initial memory size is 64KW.
CPU registers include the visible state of the processor as well as the
control registers for the interrupt system.
name size comments
P 14 program counter
A 24 accumulator A
B 24 accumulator B
X 24 index register
OV 1 overflow indicator
EM2 3 memory extension, quadrant 2
EM3 3 memory extension, quadrant 3
RL1 24 user relocation register 1
RL2 24 user relocation register 2
RL4 12 kernel relocation register
NML 1 normal mode flag
USR 1 user mode flag
MONUSR 1 monitor-to-user trap enable
ION 1 interrupt enable
INTDEF 1 interrupt defer
INTREQ 32 interrupt request flags
APIACT 5 highest active API level
APIREQ 5 highest requesting API level
XFRREQ 32 device transfer request flags
BPT 4 breakpoint switches
ALERT 6 outstanding alert number
STOP_INVINS 1 stop on invalid instruction
STOP_INVDEV 1 stop on invalid device number
STOP_INVIOP 1 stop on invalid I/O operation
INDLIM 8 maximum indirect nesting depth
EXULIM 8 maximum execute nesting depth
PCQ[0:63] 14 P prior to last branch or interrupt;
most recent P change first
WRU 8 interrupt character
The CPU can maintain a history of the most recently executed instructions.
This is controlled by the SET CPU HISTORY and SHOW CPU HISTORY commands:
SET CPU HISTORY clear history buffer
SET CPU HISTORY=0 disable history
SET CPU HISTORY=n enable history, length = n
SHOW CPU HISTORY print CPU history
SHOW CPU HISTORY=n print first n entries of CPU history
The maximum length for the history is 65536 entries.
2.2 Channels (CHAN)
The SDS 940 has up to eight I/O channels, designated W, Y, C, D, E, F, G,
and H. W, Y, C, and D are time-multiplexed communications channels (TMCC);
E, F, G, and H are direct access communications channels (DACC). Unlike
real SDS 940 channels, the simulated channels handle 6b, 12b, and 24b transfers
simultaneously. The association between a device and a channel is displayed
by the SHOW <dev> CHAN command:
SIM> SHOW LPT CHAN
channel=W
The user can change the association with the SET <dev> CHAN=<chan> command,
where <chan> is a channel letter:
SIM> SET LPT CHAN=E
SIM> SHOW LPT CHAN
channel=E
Each channel has nine registers. The registers are arrays, with entry [0]
for channel W, entry [1] for channel Y, etc.
name size comments
UAR[0:7] 6 unit address register
WCR[0:7] 15 word count register
MAR[0:7] 16 memory address register
DCR[0:7] 6 data chaining register
WAR[0:7] 24 word assembly register
CPW[0:7] 2 characters per word
CNT[0:7] 3 character count
MODE[0:7] 12 channel mode (from EOM instruction)
FLAG[0:7] 9 channel flags
The user can display all the registers in a channel with the command:
SHOW CHAN channel-letter
2.3 Console Input (TTI)
The console input (TTI) polls the console keyboard for input. It
implements these registers:
name size comments
BUF 6 data buffer
XFR 1 transfer ready flag
POS 32 number of characters input
TIME 24 polling interval
By default, the console input is assigned to channel W.
2.4 Console Output (TTO)
The console output (TTO) writes to the simulator console window. It
implements these registers:
name size comments
BUF 6 data buffer
XFR 1 transfer ready flag
POS 32 number of characters input
TIME 24 time from I/O initiation to interrupt
By default, the console output is assigned to channel W.
2.5 Paper Tape Reader (PTR)
The paper tape reader (PTR) reads data from a disk file. The POS
register specifies the number of the next data item to be read. Thus,
by changing POS, the user can backspace or advance the reader.
The paper tape reader implements these registers:
name size comments
BUF 6 data buffer
XFR 1 transfer ready flag
SOR 1 start of record flag
CHAN 4 active channel
POS 32 number of characters input
TIME 24 time from I/O initiation to interrupt
STOP_IOE 1 stop on I/O error
Error handling is as follows:
error STOP_IOE processed as
not attached 1 report error and stop
0 out of tape
end of file 1 report error and stop
0 out of tape
OS I/O error x report error and stop
By default, the paper tape reader is assigned to channel W.
2.6 Paper Tape Punch (PTP)
The paper tape punch (PTP) writes data to a disk file. The POS
register specifies the number of the next data item to be written.
Thus, by by changing POS, the user can backspace or advance the punch.
The paper tape punch implements these registers:
name size comments
BUF 6 data buffer
XFR 1 transfer ready flag
LDR 1 punch leader flag
CHAN 4 active channel
POS 32 number of characters input
TIME 24 time from I/O initiation to interrupt
STOP_IOE 1 stop on I/O error
Error handling is as follows:
error STOP_IOE processed as
not attached 1 report error and stop
0 out of tape
OS I/O error x report error and stop
By default, the paper tape punch is assigned to channel W.
2.7 Line Printer (LPT)
The line printer (LPT) writes data to a disk file. The POS register
specifies the number of the next data item to be written. Thus,
by changing POS, the user can backspace or advance the printer.
The line printer implements these registers:
name size comments
BUF[0:131] 8 data buffer
BPTR 8 buffer pointer
XFR 1 transfer ready flag
ERR 1 error flag
CHAN 4 active channel
CCT[0:131] 8 carriage control tape
CCTP 8 pointer into carriage control tape
CCTL 8 length of carriage control tape
SPCINST 24 spacing instruction
POS 32 number of characters input
CTIME 24 intercharacter time
PTIME 24 print time
STIME 24 space time
STOP_IOE 1 stop on I/O error
Error handling is as follows:
error STOP_IOE processed as
not attached 1 report error and stop
0 out of paper
OS I/O error x report error and stop
By default, the line printer is assigned to channel W.
2.8 Real-Time Clock (RTC)
The real-time clock (RTC) frequency can be adjusted as follows:
SET RTC 60HZ set frequency to 60Hz
SET RTC 50HZ set frequency to 50Hz
The default is 60Hz.
The clock implements these registers:
name size comments
PIE 1 interrupt enable
TIME 24 tick interval
The real-time clock autocalibrates; the clock interval is adjusted up or
down so that the clock tracks actual elapsed time.
2.9 Terminal Multiplexor (MUX)
The terminal multiplexor provides 32 asynchronous interfaces. In Genie
mode, the interfaces are hard-wired; in SDS mode, they implement modem
control. The multiplexor has two controllers: MUX for the scanner, and
MUXL for the individual lines. The terminal multiplexor performs input
and output through Telnet sessions connected to a user-specified port.
The ATTACH command specifies the port to be used:
ATTACH MUX <port> set up listening port
where port is a decimal number between 1 and 65535 that is not being used
for other TCP/IP activities.
Each line (each unit of MUXL) supports one option: UC, when set, causes
lower case input characters to be automatically converted to upper case.
In addition, each line supports output logging. The SET MUXLn LOG command
enables logging on a line:
SET MUXLn filename log output of line n to filename
The SET MUXLn NOLOG command disables logging and closes the open log
file, if any.
Once MUX is attached and the simulator is running, the multiplexor listens
for connections on the specified port. It assumes that the incoming
connections are Telnet connections. The connections remain open until
disconnected either by the Telnet client, a SET MUX DISCONNECT command,
or a DETACH MUX command.
The SHOW MUX CONNECTIONS command displays the current connections to the
extra terminals. The SHOW MUX STATISTICS command displays statistics for
active connections. The SET MUXLn DISCONNECT command disconnects line n.
The controller (MUX) implements these registers:
name size comments
STA[0:31] 6 status, lines 0 to 31
RBUF[0:31] 8 receive buffer, lines 0 to 31
XBUF[0:31] 8 transmit buffer, lines 0 to 31
FLAGS[0:127] 1 line flags, 0 to 3 for line 0,
4 to 7 for line 1, etc
SCAN 7 scanner current flag number
SLCK 1 scanner locked flag
TPS 8 character polls per second
The lines (MUXL) implements these registers:
name size comments
TIME[0:31] 24 transmit time, lines 0 to 31
The terminal multiplexor does not support save and restore. All open
connections are lost when the simulator shuts down or MUX is detached.
2.10 Project Genie Drum (DRM)
The Project Genie drum (DRM) implements these registers:
name size comments
DA 19 drum address
CA 16 core address
WC 14 word count
PAR 12 cumulative sector parity
RW 1 read/write flag
ERR 1 error flag
STA 2 drum state
FTIME 24 channel program fetch time
XTIME 24 interword transfer time
STOP_IOE 1 stop on I/O error
Error handling is as follows:
error STOP_IOE processed as
not attached 1 report error and stop
0 drum not ready
Drum data files are buffered in memory; therefore, end of file and OS
I/O errors cannot occur. Unlike conventional SDS 940 devices, the Project
Genie drum does not use a channel.
2.11 Rapid Access (fixed head) Disk (RAD)
The rapid access disk (RAD) implements these registers:
name size comments
DA 15 disk address
SA 6 sector word address
BP 1 sector byte pointer
XFR 1 data transfer flag
NOBD 1 inhibit increment across track
ERR 1 error flag
CHAN 4 active channel
PROT 8 write protect switches
TIME 24 interval between halfword transfers
STOP_IOE 1 stop on I/O error
Error handling is as follows:
error STOP_IOE processed as
not attached 1 report error and stop
0 disk not ready
The rapid access disk is buffered in memory; end of file and OS I/O errors
cannot occur. By default, the rapid access disk is assigned to channel E.
2.12 Moving Head Disk (DSK)
DSK options include the ability to make the drive write enabled or write
locked:
SET RAD LOCKED set write locked
SET RAD WRITEENABLED set write enabled
The moving head disk implements these registers:
name size comments
BUF[0:63] 8 transfer buffer
BPTR 9 buffer pointer
BLNT 9 buffer length
DA 21 disk address
INST 24 disk instruction
XFR 1 data transfer flag
ERR 1 error flag
CHAN 4 active channel
WTIME 24 interval between character transfers
STIME 24 seek interval
STOP_IOE 1 stop on I/O error
Error handling is as follows:
error STOP_IOE processed as
not attached 1 report error and stop
0 disk not ready
end of file x assume rest of disk is zero
OS I/O error x report error and stop
By default, the moving head disk is assigned to channel F.
2.13 Magnetic Tape (MT)
MT options include the ability to make units write enabled or write locked.
SET MTn LOCKED set unit n write locked
SET MTn WRITEENABLED set unit n write enabled
Units can also be set ENABLED or DISABLED.
The magnetic tape implements these registers:
name size comments
BUF[0:131071] 8 transfer buffer
BPTR 18 buffer pointer
BLNT 18 buffer length
XFR 1 data transfer flag
CHAN 4 active channel
INST 24 magtape instruction
EOF 1 end-of-file flag
GAP 1 inter-record gap flag
SKIP 1 skip data flag
CTIME 24 interval between character transfers
GTIME 24 gap interval
POS[0:7] 32 position, drives 0:7
STOP_IOE 1 stop on I/O error
Error handling is as follows:
error processed as
not attached tape not ready; if STOP_IOE, stop
end of file end of tape
OS I/O error end of tape; if STOP_IOE, stop
By default, the magnetic tape is assigned to channel W.
2.13 Symbolic Display and Input
The SDS 940 simulator implements symbolic display and input. Display is
controlled by command line switches:
-a display as ASCII character
-c display as four character SDS string
-m display instruction mnemonics
Input parsing is controlled by the first character typed in or by command
line switches:
' or -a ASCII character
" or -c four character SDS string
alphabetic instruction mnemonic
numeric octal number
Instruction input uses (more or less) standard SDS 940 assembler syntax.
There are eight instruction classes:
class operands examples comments
no operand none EIR
POP (prog op) op,addr{,tag} POP 66,100
I/O addr{,tag} EOM 1266
mem reference addr{,tag} LDA 400,2
STA* 300 indirect addr
reg change op op op... CLA CLB opcodes OR
shift cnt{,tag} LSH 10
chan command chan ALC W
chan test chan CAT Y
All numbers are octal. Channel designators can be alphabetic (W, Y, C, D, E,
F, G, H) or numeric (0-7). Tags must be 0-7, with 2 indicating indexing.

View file

@ -1,6 +1,6 @@
/* sds_mt.c: SDS 940 magnetic tape simulator /* sds_mt.c: SDS 940 magnetic tape simulator
Copyright (c) 2001-2005, Robert M. Supnik Copyright (c) 2001-2006, Robert M. Supnik
Permission is hereby granted, free of charge, to any person obtaining a Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"), copy of this software and associated documentation files (the "Software"),
@ -25,6 +25,7 @@
mt 7 track magnetic tape mt 7 track magnetic tape
16-Feb-06 RMS Added tape capacity checking
07-Dec-04 RMS Added read-only file support 07-Dec-04 RMS Added read-only file support
25-Apr-03 RMS Revised for extended file support 25-Apr-03 RMS Revised for extended file support
28-Mar-03 RMS Added multiformat support 28-Mar-03 RMS Added multiformat support
@ -154,6 +155,8 @@ MTAB mt_mod[] = {
{ MTUF_WLK, MTUF_WLK, "write locked", "LOCKED", NULL }, { MTUF_WLK, MTUF_WLK, "write locked", "LOCKED", NULL },
{ MTAB_XTD|MTAB_VUN, 0, "FORMAT", "FORMAT", { MTAB_XTD|MTAB_VUN, 0, "FORMAT", "FORMAT",
&sim_tape_set_fmt, &sim_tape_show_fmt, NULL }, &sim_tape_set_fmt, &sim_tape_show_fmt, NULL },
{ MTAB_XTD|MTAB_VUN, 0, "CAPACITY", "CAPACITY",
&sim_tape_set_capac, &sim_tape_show_capac, NULL },
{ MTAB_XTD|MTAB_VDV, 0, "CHANNEL", "CHANNEL", { MTAB_XTD|MTAB_VDV, 0, "CHANNEL", "CHANNEL",
&set_chan, &show_chan, NULL }, &set_chan, &show_chan, NULL },
{ 0 } { 0 }
@ -333,7 +336,12 @@ if ((uptr->flags & UNIT_ATT) == 0) { /* attached? */
} }
if (mt_inst & CHC_REV) /* reverse? */ if (mt_inst & CHC_REV) /* reverse? */
st = sim_tape_rdrecr (uptr, mtxb, &tbc, MT_MAXFR); /* read rec rev */ st = sim_tape_rdrecr (uptr, mtxb, &tbc, MT_MAXFR); /* read rec rev */
else st = sim_tape_rdrecf (uptr, mtxb, &tbc, MT_MAXFR); /* no, fwd */ else { /* no, fwd */
t_bool passed_eot = sim_tape_eot (uptr); /* passed EOT? */
st = sim_tape_rdrecf (uptr, mtxb, &tbc, MT_MAXFR);
if (!passed_eot && sim_tape_eot (uptr)) /* just passed eot? */
uptr->eotf = 1;
}
if (st == MTSE_TMK) { /* tape mark? */ if (st == MTSE_TMK) { /* tape mark? */
mt_eof = 1; /* set eof flag */ mt_eof = 1; /* set eof flag */
mtxb[0] = mtxb[1] = 017; /* EOR char */ mtxb[0] = mtxb[1] = 017; /* EOR char */
@ -390,10 +398,13 @@ if (dev & DEV_MTS) { /* erase? */
st = sim_tape_wreom (uptr); /* write eom */ st = sim_tape_wreom (uptr); /* write eom */
} }
else { else {
t_bool passed_eot = sim_tape_eot (uptr); /* passed EOT? */
if ((mt_bptr == 1) && (mtxb[0] == 017) && /* wr eof? */ if ((mt_bptr == 1) && (mtxb[0] == 017) && /* wr eof? */
((mt_inst & 01670) == 00050)) ((mt_inst & 01670) == 00050))
st = sim_tape_wrtmk (uptr); /* write tape mark */ st = sim_tape_wrtmk (uptr); /* write tape mark */
else st = sim_tape_wrrecf (uptr, mtxb, mt_bptr); /* write record */ else st = sim_tape_wrrecf (uptr, mtxb, mt_bptr); /* write record */
if (!passed_eot && sim_tape_eot (uptr)) /* just passed EOT? */
uptr->eotf = 1;
} }
mt_bptr = 0; mt_bptr = 0;
if (st != MTSE_OK) mt_set_err (uptr); /* error? */ if (st != MTSE_OK) mt_set_err (uptr); /* error? */

View file

@ -11,6 +11,49 @@
11. CIS: CMPP3/CMPP4 using wrong arguments to ReadDstr. 11. CIS: CMPP3/CMPP4 using wrong arguments to ReadDstr.
12. CPU, OCTA: CVTfi with integer overflow not setting trap if PSW<iv> = 1. 12. CPU, OCTA: CVTfi with integer overflow not setting trap if PSW<iv> = 1.
13. STDDEV: read of ICR was missing the call parameter. 13. STDDEV: read of ICR was missing the call parameter.
14. ACBD/G: testing wrong operand register to get limit sign.
15. CPU: faults not clearing PSL<tp>.
16. ADAWI: register mode implemented incorrectly.
17. MOVTC: condition codes not preserved through page fault.
18. MOVTUC: condition codes not preserved through page fault.
19. MOVTUC: escape tested against untranslated rather than translated character.
20. CVTPT: condition code and decimal overflow calculation incorrect.
21. CVTPS: condition code and decimal overflow calculation incorrect.
22. CVTPL: if destination is register, result is stored after register updates.
23. CVTPL: integer overflow set <C> rather than <V>.
24. all decimal string: 11/780 does not validate characters in decimal strings.
25. EDITPC: condition codes not preserved through page fault.
26. EDITPC EO$INSERT: inserts sign instead of fill.
27. EDITPC EO$BLANK_ZERO: address off by one.
28. EDITPC EO$BLANK_ZERO: not testing for <C> set.
29. EDITPC EO$LOAD_PLUS: not skipping character if test fails.
30. EDITPC EO$LOAD_MINUS: not skipping character if test fails.
31. Compatibility mode: SXT not implemented.
32. Compatibility mode: XOR operands fetched in wrong order.
33. MNEGH: condition codes set from original sign.
34. MNEGH: <C> not cleared.
35. H_floating quad precision integer routines (add, inc, neg): carry propagation incorrect.
36. H_floating packup routines: test for zero used exponent not fraction.
37. MULH: carries out of floating accumulator lost.
38. DIVH: stores wrong operand as result.
39. POLYF/D/G: truncation after add not needed.
40. POLYF/D/G: early SRM requires truncation to 31b/63b, not 32b/64b.
41. POLYF/D/G/H: exits too early if argument is zero.
42. POLYD/G/H: calculates address of residual pointer result incorrectly.
43. POLYD/G: performs single precision rather than double precision multiply.
44. POLYH: fails to truncate intermediate result from 128b to 127b.
45. POLYF/D/G/H: internal add routine must test fraction rather than exponent to
detect zero, POLYx can create "denormalized" intermediate result.
46. EMODH: concatenate 16b of extension operand instead of 15b.
47. Specifier flows: modify flows testing for read access rather than write access.
48. Quad/octa writes: wrong address reported on faulting cross-page writes.
49. Memory management: 11/780 implements access control test on first level PTE's.
50. LDPCTX: 11/780 implements mbz tests on PCB fields.
51. LDPCTX/MTPR: 11/780 validity checks PCBB, SCBB, SBR, SLR, P0BR, P0LR, P1BR, P1LR.
52. TMR: tmr_inc not updated in standard (100Hz) mode.

View file

@ -1,6 +1,6 @@
/* vax780_defs.h: VAX 780 model-specific definitions file /* vax780_defs.h: VAX 780 model-specific definitions file
Copyright (c) 2004-2005, Robert M Supnik Copyright (c) 2004-2006, Robert M Supnik
Permission is hereby granted, free of charge, to any person obtaining a Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"), copy of this software and associated documentation files (the "Software"),
@ -23,6 +23,9 @@
used in advertising or otherwise to promote the sale, use or other dealings used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from Robert M Supnik. in this Software without prior written authorization from Robert M Supnik.
17-May-2006 RMS Added CR11/CD11 support (from John Dundas)
10-May-2006 RMS Added model-specific reserved operand check macros
This file covers the VAX 11/780, the first VAX. This file covers the VAX 11/780, the first VAX.
System memory map System memory map
@ -113,6 +116,16 @@
#define MT_SBIQC 54 /* SBI timeout clear */ #define MT_SBIQC 54 /* SBI timeout clear */
#define MT_MBRK 60 /* microbreak */ #define MT_MBRK 60 /* microbreak */
/* Machine specific reserved operand tests */
#define ML_PA_TEST(r) if ((r) & 0xC0000003) RSVD_OPND_FAULT
#define ML_LR_TEST(r) if ((uint32)(r) > 0x200000) RSVD_OPND_FAULT
#define ML_BR_TEST(r) if ((((r) & 0xC0000000) != 0x80000000) || \
((r) & 0x00000003)) RSVD_OPND_FAULT
#define LP_AST_TEST(r) if ((r) > AST_MAX) RSVD_OPND_FAULT
#define LP_MBZ84_TEST(r) if ((r) & 0xF8C00000) RSVD_OPND_FAULT
#define LP_MBZ92_TEST(r) if ((r) & 0x7FC00000) RSVD_OPND_FAULT
/* Memory */ /* Memory */
#define MAXMEMWIDTH 23 /* max mem, MS780C */ #define MAXMEMWIDTH 23 /* max mem, MS780C */
@ -265,6 +278,8 @@ typedef struct {
#define IOLN_TQ 004 #define IOLN_TQ 004
#define IOBA_XU (IOPAGEBASE + 014510) /* DEUNA/DELUA */ #define IOBA_XU (IOPAGEBASE + 014510) /* DEUNA/DELUA */
#define IOLN_XU 010 #define IOLN_XU 010
#define IOBA_CR (IOPAGEBASE + 017160) /* CD/CR/CM */
#define IOLN_CR 010
#define IOBA_RX (IOPAGEBASE + 017170) /* RX11 */ #define IOBA_RX (IOPAGEBASE + 017170) /* RX11 */
#define IOLN_RX 004 #define IOLN_RX 004
#define IOBA_RY (IOPAGEBASE + 017170) /* RXV21 */ #define IOBA_RY (IOPAGEBASE + 017170) /* RXV21 */
@ -295,6 +310,7 @@ typedef struct {
#define INT_V_LPT 0 /* BR4 */ #define INT_V_LPT 0 /* BR4 */
#define INT_V_PTR 1 #define INT_V_PTR 1
#define INT_V_PTP 2 #define INT_V_PTP 2
#define INT_V_CR 3
#define INT_DZRX (1u << INT_V_DZRX) #define INT_DZRX (1u << INT_V_DZRX)
#define INT_DZTX (1u << INT_V_DZTX) #define INT_DZTX (1u << INT_V_DZTX)
@ -305,9 +321,10 @@ typedef struct {
#define INT_TS (1u << INT_V_TS) #define INT_TS (1u << INT_V_TS)
#define INT_RY (1u << INT_V_RY) #define INT_RY (1u << INT_V_RY)
#define INT_XU (1u << INT_V_XU) #define INT_XU (1u << INT_V_XU)
#define INT_LPT (1u << INT_V_LPT)
#define INT_PTR (1u << INT_V_PTR) #define INT_PTR (1u << INT_V_PTR)
#define INT_PTP (1u << INT_V_PTP) #define INT_PTP (1u << INT_V_PTP)
#define INT_LPT (1u << INT_V_LPT) #define INT_CR (1u << INT_V_CR)
#define IPL_DZRX (0x15 - IPL_HMIN) #define IPL_DZRX (0x15 - IPL_HMIN)
#define IPL_DZTX (0x15 - IPL_HMIN) #define IPL_DZTX (0x15 - IPL_HMIN)
@ -318,9 +335,10 @@ typedef struct {
#define IPL_TS (0x15 - IPL_HMIN) #define IPL_TS (0x15 - IPL_HMIN)
#define IPL_RY (0x15 - IPL_HMIN) #define IPL_RY (0x15 - IPL_HMIN)
#define IPL_XU (0x15 - IPL_HMIN) #define IPL_XU (0x15 - IPL_HMIN)
#define IPL_LPT (0x14 - IPL_HMIN)
#define IPL_PTR (0x14 - IPL_HMIN) #define IPL_PTR (0x14 - IPL_HMIN)
#define IPL_PTP (0x14 - IPL_HMIN) #define IPL_PTP (0x14 - IPL_HMIN)
#define IPL_LPT (0x14 - IPL_HMIN) #define IPL_CR (0x14 - IPL_HMIN)
/* Device vectors */ /* Device vectors */
@ -334,6 +352,7 @@ typedef struct {
#define VEC_LPT 0200 #define VEC_LPT 0200
#define VEC_HK 0210 #define VEC_HK 0210
#define VEC_TS 0224 #define VEC_TS 0224
#define VEC_CR 0230
#define VEC_TQ 0260 #define VEC_TQ 0260
#define VEC_RX 0264 #define VEC_RX 0264
#define VEC_RY 0264 #define VEC_RY 0264

File diff suppressed because it is too large Load diff

250
VAX/vax780_fload.c Normal file
View file

@ -0,0 +1,250 @@
/* vax780_fload.c: VAX780 FLOAD command
Copyright (c) 2006, Robert M Supnik
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Except as contained in this notice, the name of Robert M Supnik shall not be
used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from Robert M Supnik.
This code is based on the CP/M RT11 utility, which bears the following
copyrights:
copyright (c) 1980, William C. Colley, III
Rev. 1.2 -- Craig Davenport - Incitec Ltd (Feb 1984)
P O Box 140
Morningside,
Qld 4170,
Australia.
-- Modified for Digital Research C compiler under CP/M-86
-- Assebmbly language routines added for BIOS calls etc.
Thanks to Phil Budne for the original adaptation of RT11 to SimH.
*/
#include "vax_defs.h"
#include <ctype.h>
#define BLK_SIZE 256 /* RT11 block size */
/* Floppy disk parameters */
#define BPT 26 /* blocks/track */
#define NTRACKS 77
#define SECTOR_SKEW 2
#define TRACK_SKEW 6
#define TRACK_OFFSET 1 /* track 0 unused */
/* RT11 directory segment (2 blocks = 512 16b words) */
#define DS_TOTAL 0 /* segments available */
#define DS_MAX 31 /* segment max */
#define DS_NEXT 1 /* zero for last segment */
#define DS_HIGHEST 2 /* only in 1st segment */
#define DS_EXTRA 3 /* extra bytes/entry */
#define DS_FIRST 4 /* first block */
#define DS_ENTRIES 5 /* start of entries */
#define DS_SIZE (2 * BLK_SIZE) /* segment size, words */
/* RT11 directory entry offsets */
#define DE_STATUS 0 /* status (odd byte) */
#define TENTAT 001 /* tentative */
#define EMPTY 002
#define PERM 004
#define ENDSEG 010 /* end of segment */
#define DE_NAME 1 /* file name */
#define DE_FLNT 4 /* file length */
#define DE_SIZE 7 /* entry size in words */
#define DE_GET_STAT(x) (((x) >> 8) & 0377)
extern UNIT cpu_unit;
extern UNIT fl_unit;
t_bool rtfile_parse (char *pntr, uint16 *file_name);
uint32 rtfile_lookup (uint16 *file_name, uint32 *start);
uint32 rtfile_ator50 (uint32 ascii);
t_bool rtfile_read (uint32 block, uint32 count, uint16 *buffer);
uint32 rtfile_find (uint32 block, uint32 sector);
extern void WriteW (uint32 pa, int32 val);
/* FLOAD file_name {file_origin} */
t_stat vax780_fload (int flag, char *cptr)
{
char gbuf[CBUFSIZE];
uint16 file_name[3], blkbuf[BLK_SIZE];
t_stat r;
uint32 i, j, start, size, origin;
if ((fl_unit.flags & UNIT_ATT) == 0) /* floppy attached? */
return SCPE_UNATT;
if (*cptr == 0) return SCPE_2FARG;
cptr = get_glyph (cptr, gbuf, 0); /* get file name */
if (!rtfile_parse (gbuf, file_name)) /* legal file name? */
return SCPE_ARG;
if ((size = rtfile_lookup (file_name, &start)) == 0) /* file on floppy? */
return SCPE_ARG;
if (*cptr) { /* origin? */
origin = (uint32) get_uint (cptr, 16, MEMSIZE, &r);
if ((r != SCPE_OK) || (origin & 1)) /* must be even */
return SCPE_ARG;
}
else origin = 512; /* no, use default */
for (i = 0; i < size; i++) { /* loop thru blocks */
if (!rtfile_read (start + i, 1, blkbuf)) /* read block */
return SCPE_FMT;
for (j = 0; j < BLK_SIZE; j++) { /* loop thru words */
if (ADDR_IS_MEM (origin))
WriteW (origin, blkbuf[j]);
else return SCPE_NXM;
origin = origin + 2;
}
}
return SCPE_OK;
}
/* Parse an RT11 file name and convert it to radix-50 */
t_bool rtfile_parse (char *pntr, uint16 *file_name)
{
char c;
uint16 d;
uint32 i, j;
file_name[0] = file_name[1] = file_name[2] = 0; /* zero file name */
for (i = 0; i < 2; i++) { /* 6 characters */
for (j = 0; j < 3; j++) {
c = *pntr;
if ((c == '.') || (c == 0)) d = 0; /* fill if . or end */
else {
if ((d = rtfile_ator50 (c)) == 0) return FALSE;
pntr++;
}
file_name[i] = (file_name[i] * 050) + d; /* merge into name */
}
}
if (file_name[0] == 0) return FALSE; /* no name? lose */
while ((c = *pntr++) != '.') { /* scan for . */
if (c == 0) return TRUE; /* end? done */
}
for (i = 0; i < 3; i++) { /* 3 characters */
c = *pntr;
if (c == 0) d = 0; /* fill if end */
else {
if ((d = rtfile_ator50 (c)) == 0) return FALSE;
pntr++;
}
file_name[2] = (file_name[2] * 050) + d; /* merge into ext */
}
return TRUE;
}
/* ASCII to radix-50 conversion */
uint32 rtfile_ator50 (uint32 ascii)
{
static char *r50 = " ABCDEFGHIJKLMNOPQRSTUVWXYZ$._0123456789";
char *fptr;
ascii = toupper (ascii);
if ((fptr = strchr (r50, toupper (ascii))) != NULL)
return ((uint32) (fptr - r50));
else return 0;
}
/* Lookup an RT11 file name in the directory */
uint32 rtfile_lookup (uint16 *file_name, uint32 *start)
{
uint16 dirseg[DS_SIZE];
uint32 segnum, dirent;
for (segnum = 1; /* loop thru segments */
(segnum != 0) && (segnum <= DS_MAX);
segnum = dirseg[DS_NEXT]) {
if (!rtfile_read ((segnum * 2) + 4, 2, dirseg)) /* read segment */
return 0; /* error? */
*start = dirseg[DS_FIRST]; /* init file start */
for (dirent = DS_ENTRIES; /* loop thru entries */
(dirent < DS_SIZE) &&
(DE_GET_STAT (dirseg[dirent + DE_STATUS]) != ENDSEG);
dirent += DE_SIZE + (dirseg[DS_EXTRA] / 2)) {
if ((DE_GET_STAT (dirseg[dirent + DE_STATUS]) == PERM) &&
(dirseg[dirent + DE_NAME + 0] == file_name[0]) &&
(dirseg[dirent + DE_NAME + 1] == file_name[1]) &&
(dirseg[dirent + DE_NAME + 2] == file_name[2]))
return dirseg[dirent + DE_FLNT];
*start += dirseg[dirent + DE_FLNT]; /* incr file start */
}
}
return 0;
}
/* Read blocks */
t_stat rtfile_read (uint32 block, uint32 count, uint16 *buffer)
{
uint32 i, j;
uint32 pos;
uint8 *fbuf = fl_unit.filebuf;
for (; count > 0; count--, block++) {
for (i = 0; i < 4; i++) { /* 4 sectors/block */
pos = rtfile_find (block, i); /* position */
if ((pos + 128) >= (uint32) fl_unit.capac) /* off end of disk? */
return FALSE;
for (j = 0; j < 128; j = j + 2) /* copy 128 bytes */
*buffer++ = (((uint16) fbuf[pos + j + 1]) << 8) |
((uint16) fbuf[pos + j]);
}
}
return TRUE;
}
/* Map an RT-11 block number to a physical byte number */
uint32 rtfile_find (uint32 block, uint32 sector)
{
uint32 ls, lt, pt, ps;
uint32 off, bb;
/* get logical block, track & sector */
bb = (block * 4) + sector;
lt = bb / BPT;
ls = bb % BPT;
/* logic from 4.3BSD rx.c
* calculate phys track & sector
* 2:1 skew, 6 sector skew for each track
*/
pt = lt + TRACK_OFFSET;
ps = ((ls * SECTOR_SKEW) + (ls / (BPT / SECTOR_SKEW)) + (TRACK_SKEW * lt)) % BPT;
/* byte offset in logical disk */
off = (pt * BPT + ps) * 128;
return off;
}

View file

@ -1,6 +1,6 @@
/* vax780_sbi.c: VAX 11/780 SBI /* vax780_sbi.c: VAX 11/780 SBI
Copyright (c) 2004-2005, Robert M Supnik Copyright (c) 2004-2006, Robert M Supnik
Permission is hereby granted, free of charge, to any person obtaining a Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"), copy of this software and associated documentation files (the "Software"),
@ -26,6 +26,8 @@
This module contains the VAX 11/780 system-specific registers and devices. This module contains the VAX 11/780 system-specific registers and devices.
sbi bus controller sbi bus controller
03-May-2006 RMS Fixed writes to ACCS
*/ */
#include "vax_defs.h" #include "vax_defs.h"
@ -126,9 +128,10 @@ extern CTAB *sim_vm_cmd;
t_stat sbi_reset (DEVICE *dptr); t_stat sbi_reset (DEVICE *dptr);
void sbi_set_tmo (int32 pa); void sbi_set_tmo (int32 pa);
void uba_eval_int (void);
t_stat vax780_boot (int32 flag, char *ptr); t_stat vax780_boot (int32 flag, char *ptr);
void uba_eval_int (void); extern t_stat vax780_fload (int flag, char *cptr);
extern void Write (uint32 va, int32 val, int32 lnt, int32 acc); extern void Write (uint32 va, int32 val, int32 lnt, int32 acc);
extern int32 intexc (int32 vec, int32 cc, int32 ipl, int ei); extern int32 intexc (int32 vec, int32 cc, int32 ipl, int ei);
extern int32 iccs_rd (void); extern int32 iccs_rd (void);
@ -188,6 +191,8 @@ DEVICE sbi_dev = {
CTAB vax780_cmd[] = { CTAB vax780_cmd[] = {
{ "BOOT", &vax780_boot, RU_BOOT, { "BOOT", &vax780_boot, RU_BOOT,
"bo{ot} <device>{/R5:flg} boot device\n" }, "bo{ot} <device>{/R5:flg} boot device\n" },
{ "FLOAD", &vax780_fload, 0,
"fl{oad} <file> {<start>} load file from console floppy\n" },
{ NULL } { NULL }
}; };
@ -388,6 +393,9 @@ switch (rg) {
todr_wr (val); todr_wr (val);
break; break;
case MT_ACCS: /* ACCS (not impl) */
break;
case MT_WCSA: /* WCSA */ case MT_WCSA: /* WCSA */
wcs_addr = val & WCSA_RW; wcs_addr = val & WCSA_RW;
break; break;

View file

@ -1,6 +1,6 @@
/* vax780_stddev.c: VAX 11/780 standard I/O devices /* vax780_stddev.c: VAX 11/780 standard I/O devices
Copyright (c) 1998-2005, Robert M Supnik Copyright (c) 1998-2006, Robert M Supnik
Permission is hereby granted, free of charge, to any person obtaining a Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"), copy of this software and associated documentation files (the "Software"),
@ -29,7 +29,7 @@
todr TODR clock todr TODR clock
tmr interval timer tmr interval timer
11-May-06 RMS Revised timer logic for EVKAE
22-Nov-05 RMS Revised for new terminal processing routines 22-Nov-05 RMS Revised for new terminal processing routines
10-Mar-05 RMS Fixed bug in timer schedule routine (from Mark Hittinger) 10-Mar-05 RMS Fixed bug in timer schedule routine (from Mark Hittinger)
08-Sep-04 RMS Cloned from vax_stddev.c, vax_sysdev.c, and pdp11_rx.c 08-Sep-04 RMS Cloned from vax_stddev.c, vax_sysdev.c, and pdp11_rx.c
@ -101,7 +101,6 @@
#define TMR_CSR_W1C (TMR_CSR_ERR | TMR_CSR_DON) #define TMR_CSR_W1C (TMR_CSR_ERR | TMR_CSR_DON)
#define TMR_CSR_WR (TMR_CSR_IE | TMR_CSR_RUN) #define TMR_CSR_WR (TMR_CSR_IE | TMR_CSR_RUN)
#define TMR_INC 10000 /* usec/interval */ #define TMR_INC 10000 /* usec/interval */
#define TMR_NICR_STD ((~TMR_INC + 1) & LMASK)
#define CLK_DELAY 5000 /* 100 Hz */ #define CLK_DELAY 5000 /* 100 Hz */
#define TMXR_MULT 2 /* 50 Hz */ #define TMXR_MULT 2 /* 50 Hz */
@ -162,6 +161,7 @@ uint32 tmr_nicr = 0; /* next interval */
uint32 tmr_inc = 0; /* timer increment */ uint32 tmr_inc = 0; /* timer increment */
int32 tmr_sav = 0; /* timer save */ int32 tmr_sav = 0; /* timer save */
int32 tmr_int = 0; /* interrupt */ int32 tmr_int = 0; /* interrupt */
int32 tmr_use_100hz = 1; /* use 100Hz for timer */
int32 clk_tps = 100; /* ticks/second */ int32 clk_tps = 100; /* ticks/second */
int32 tmxr_poll = CLK_DELAY * TMXR_MULT; /* term mux poll */ int32 tmxr_poll = CLK_DELAY * TMXR_MULT; /* term mux poll */
int32 tmr_poll = CLK_DELAY; /* pgm timer poll */ int32 tmr_poll = CLK_DELAY; /* pgm timer poll */
@ -299,6 +299,7 @@ REG tmr_reg[] = {
{ HRDATA (NICR, tmr_nicr, 32) }, { HRDATA (NICR, tmr_nicr, 32) },
{ HRDATA (INCR, tmr_inc, 32), REG_HIDDEN }, { HRDATA (INCR, tmr_inc, 32), REG_HIDDEN },
{ HRDATA (SAVE, tmr_sav, 32), REG_HIDDEN }, { HRDATA (SAVE, tmr_sav, 32), REG_HIDDEN },
{ FLDATA (USE100HZ, tmr_use_100hz, 0), REG_HIDDEN },
{ FLDATA (INT, tmr_int, 0) }, { FLDATA (INT, tmr_int, 0) },
{ NULL } { NULL }
}; };
@ -476,13 +477,13 @@ return SCPE_OK;
accurately simulated due to the overhead that would be required accurately simulated due to the overhead that would be required
for 1M clock events per second. Instead, a hidden calibrated for 1M clock events per second. Instead, a hidden calibrated
100Hz timer is run (because that's what VMS expects), and a 100Hz timer is run (because that's what VMS expects), and a
gross hack is used for the interval timer. hack is used for the interval timer.
When the timer is started, the timer interval is inspected. When the timer is started, the timer interval is inspected.
if the interval is the standard 10msec, then the 100Hz timer if the interval is >= 10msec, then the 100Hz timer drives the
supplies timer interrupts next interval
if the interval is non-standard then count instructions if the interval is < 10mec, then count instructions
If the interval register is read, then its value between events If the interval register is read, then its value between events
is interpolated using the current instruction count versus the is interpolated using the current instruction count versus the
@ -502,6 +503,7 @@ void iccs_wr (int32 val)
{ {
if ((val & TMR_CSR_RUN) == 0) { /* clearing run? */ if ((val & TMR_CSR_RUN) == 0) { /* clearing run? */
sim_cancel (&tmr_unit); /* cancel timer */ sim_cancel (&tmr_unit); /* cancel timer */
tmr_use_100hz = 0;
if (tmr_iccs & TMR_CSR_RUN) /* run 1 -> 0? */ if (tmr_iccs & TMR_CSR_RUN) /* run 1 -> 0? */
tmr_icr = icr_rd (TRUE); /* update itr */ tmr_icr = icr_rd (TRUE); /* update itr */
} }
@ -531,8 +533,7 @@ uint32 delta;
if (interp || (tmr_iccs & TMR_CSR_RUN)) { /* interp, running? */ if (interp || (tmr_iccs & TMR_CSR_RUN)) { /* interp, running? */
delta = sim_grtime () - tmr_sav; /* delta inst */ delta = sim_grtime () - tmr_sav; /* delta inst */
if ((tmr_inc == TMR_INC) && /* scale large int */ if (tmr_use_100hz && (tmr_poll > TMR_INC)) /* scale large int */
(tmr_poll > TMR_INC))
delta = (uint32) ((((double) delta) * TMR_INC) / tmr_poll); delta = (uint32) ((((double) delta) * TMR_INC) / tmr_poll);
if (delta >= tmr_inc) delta = tmr_inc - 1; if (delta >= tmr_inc) delta = tmr_inc - 1;
return tmr_icr + delta; return tmr_icr + delta;
@ -554,15 +555,11 @@ tmr_nicr = val;
t_stat clk_svc (UNIT *uptr) t_stat clk_svc (UNIT *uptr)
{ {
int32 t; tmr_poll = sim_rtcn_calb (clk_tps, TMR_CLK); /* calibrate clock */
sim_activate (&clk_unit, tmr_poll); /* reactivate unit */
t = sim_rtcn_calb (clk_tps, TMR_CLK); /* calibrate clock */ tmxr_poll = tmr_poll * TMXR_MULT; /* set mux poll */
sim_activate (&clk_unit, t); /* reactivate unit */
tmr_poll = t; /* set tmr poll */
tmxr_poll = t * TMXR_MULT; /* set mux poll */
todr_reg = todr_reg + 1; /* incr TODR */ todr_reg = todr_reg + 1; /* incr TODR */
if ((tmr_iccs & TMR_CSR_RUN) && /* timer running? */ if ((tmr_iccs & TMR_CSR_RUN) && tmr_use_100hz) /* timer on, std intvl? */
(tmr_nicr == TMR_NICR_STD)) /* standard interval? */
tmr_incr (TMR_INC); /* do timer service */ tmr_incr (TMR_INC); /* do timer service */
return SCPE_OK; return SCPE_OK;
} }
@ -606,24 +603,23 @@ return;
void tmr_sched (void) void tmr_sched (void)
{ {
tmr_sav = sim_grtime (); /* save intvl base */ tmr_sav = sim_grtime (); /* save intvl base */
if (tmr_nicr != TMR_NICR_STD) { /* non-std interval? */ tmr_inc = (~tmr_icr + 1); /* inc = interval */
tmr_inc = (~tmr_icr + 1); /* inc = interval */ if (tmr_inc == 0) tmr_inc = 1;
if (tmr_inc == 0) tmr_inc = 1; if (tmr_inc < TMR_INC) { /* 100Hz multiple? */
sim_activate (&tmr_unit, tmr_inc); sim_activate (&tmr_unit, tmr_inc); /* schedule timer */
tmr_use_100hz = 0;
} }
return; /* let clk handle */ else tmr_use_100hz = 1; /* let clk handle */
return;
} }
/* 100Hz clock reset */ /* 100Hz clock reset */
t_stat clk_reset (DEVICE *dptr) t_stat clk_reset (DEVICE *dptr)
{ {
int32 t; tmr_poll = sim_rtcn_init (clk_unit.wait, TMR_CLK); /* init 100Hz timer */
sim_activate (&clk_unit, tmr_poll); /* activate 100Hz unit */
t = sim_rtcn_init (clk_unit.wait, TMR_CLK); /* init 100Hz timer */ tmxr_poll = tmr_poll * TMXR_MULT; /* set mux poll */
sim_activate (&clk_unit, t); /* activate 100Hz unit */
tmr_poll = t; /* set tmr poll */
tmxr_poll = t * TMXR_MULT; /* set mux poll */
return SCPE_OK; return SCPE_OK;
} }
@ -635,6 +631,7 @@ tmr_iccs = 0;
tmr_icr = 0; tmr_icr = 0;
tmr_nicr = 0; tmr_nicr = 0;
tmr_int = 0; tmr_int = 0;
tmr_use_100hz = 1;
sim_cancel (&tmr_unit); /* cancel timer */ sim_cancel (&tmr_unit); /* cancel timer */
if (sim_switches & SWMASK ('P')) todr_powerup (); /* powerup? set TODR */ if (sim_switches & SWMASK ('P')) todr_powerup (); /* powerup? set TODR */
return SCPE_OK; return SCPE_OK;

View file

@ -1,6 +1,6 @@
/* vax_syslist.c: VAX device list /* vax_syslist.c: VAX device list
Copyright (c) 1998-2005, Robert M Supnik Copyright (c) 1998-2006, Robert M Supnik
Permission is hereby granted, free of charge, to any person obtaining a Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"), copy of this software and associated documentation files (the "Software"),
@ -23,7 +23,8 @@
used in advertising or otherwise to promote the sale, use or other dealings used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from Robert M Supnik. in this Software without prior written authorization from Robert M Supnik.
01-Oct-2004 RMS Cloned from vax_sys.c 17-May-06 RMS Added CR11/CD11 support (from John Dundas)
01-Oct-04 RMS Cloned from vax_sys.c
*/ */
#include "vax_defs.h" #include "vax_defs.h"
@ -40,6 +41,7 @@ extern DEVICE clk_dev;
extern DEVICE tmr_dev; extern DEVICE tmr_dev;
extern DEVICE tti_dev, tto_dev; extern DEVICE tti_dev, tto_dev;
extern DEVICE fl_dev; extern DEVICE fl_dev;
extern DEVICE cr_dev;
extern DEVICE lpt_dev; extern DEVICE lpt_dev;
extern DEVICE rq_dev, rqb_dev, rqc_dev, rqd_dev; extern DEVICE rq_dev, rqb_dev, rqc_dev, rqd_dev;
extern DEVICE rl_dev; extern DEVICE rl_dev;
@ -72,6 +74,7 @@ DEVICE *sim_devices[] = {
&tto_dev, &tto_dev,
&fl_dev, &fl_dev,
&dz_dev, &dz_dev,
&cr_dev,
&lpt_dev, &lpt_dev,
&rp_dev, &rp_dev,
&rl_dev, &rl_dev,

View file

@ -26,6 +26,16 @@
On a full VAX, this module simulates the VAX commercial instruction set (CIS). On a full VAX, this module simulates the VAX commercial instruction set (CIS).
On a subset VAX, this module implements the emulated instruction fault. On a subset VAX, this module implements the emulated instruction fault.
16-May-06 RMS Fixed bug in length calculation (found by Tim Stark)
03-May-06 RMS Fixed MOVTC, MOVTUC to preserve cc's through page faults
Fixed MOVTUC to stop on translated == escape
Fixed CVTPL to set registers before destination reg write
Fixed CVTPL to set correct cc bit on overflow
Fixed EDITPC to preserve cc's through page faults
Fixed EDITPC EO$BLANK_ZERO count, cc test
Fixed EDITPC EO$INSERT to insert fill instead of blank
Fixed EDITPC EO$LOAD_PLUS/MINUS to skip character
(all reported by Tim Stark)
12-Apr-04 RMS Cloned from pdp11_cis.c and vax_cpu1.c 12-Apr-04 RMS Cloned from pdp11_cis.c and vax_cpu1.c
Zero length decimal strings require either zero bytes (trailing) or one byte Zero length decimal strings require either zero bytes (trailing) or one byte
@ -98,8 +108,9 @@ extern int32 eval_int (void);
int32 op_cis (int32 *op, int32 cc, int32 opc, int32 acc) int32 op_cis (int32 *op, int32 cc, int32 opc, int32 acc)
{ {
int32 i, j, c, t, pop, rpt, V; int32 i, j, c, t, pop, rpt, V;
int32 match, fill, sign, shift, ncc; int32 match, fill, sign, shift;
int32 ldivd, ldivr; int32 ldivd, ldivr;
int32 lenl, lenp;
uint32 nc, d, result; uint32 nc, d, result;
t_stat r; t_stat r;
DSTR accum, src1, src2, dst; DSTR accum, src1, src2, dst;
@ -120,7 +131,7 @@ switch (opc) { /* case on opcode */
R[1] = source string address R[1] = source string address
R[2] = number of bytes remaining to move R[2] = number of bytes remaining to move
R[3] = table address R[3] = table address
R[4] = destination string length R[4] = saved cc's/destination string length
R[5] = destination string address R[5] = destination string address
Condition codes: Condition codes:
@ -141,23 +152,23 @@ switch (opc) { /* case on opcode */
SETPC (fault_PC + STR_GETDPC (R[0])); /* reset PC */ SETPC (fault_PC + STR_GETDPC (R[0])); /* reset PC */
fill = STR_GETCHR (R[0]); /* get fill */ fill = STR_GETCHR (R[0]); /* get fill */
R[2] = R[2] & STR_LNMASK; /* remaining move */ R[2] = R[2] & STR_LNMASK; /* remaining move */
R[4] = R[4] & STR_LNMASK; cc = (R[4] >> 16) & CC_MASK; /* restore cc's */
} }
else { else {
CC_CMP_W (op[0], op[4]); /* set cc's */
R[0] = STR_PACK (op[2], op[0]); /* src len, fill */ R[0] = STR_PACK (op[2], op[0]); /* src len, fill */
R[1] = op[1]; /* src addr */ R[1] = op[1]; /* src addr */
fill = op[2]; /* set fill */ fill = op[2]; /* set fill */
R[3] = op[3]; /* table addr */ R[3] = op[3]; /* table addr */
R[4] = op[4]; /* dst len */ R[4] = op[4] | ((cc & CC_MASK) << 16); /* dst len + cc's */
R[5] = op[5]; /* dst addr */ R[5] = op[5]; /* dst addr */
CC_CMP_W (op[0], op[4]); /* set cc's */
R[2] = (op[0] < op[4])? op[0]: op[4]; /* remaining move */ R[2] = (op[0] < op[4])? op[0]: op[4]; /* remaining move */
PSL = PSL | PSL_FPD; /* set FPD */ PSL = PSL | PSL_FPD; /* set FPD */
} }
if (R[2]) { /* move to do? */ if (R[2]) { /* move to do? */
int32 mvl; int32 mvl;
mvl = R[0] & STR_LNMASK; /* orig move len */ mvl = R[0] & STR_LNMASK; /* orig move len */
if (mvl >= R[4]) mvl = R[4]; if (mvl >= (R[4] & STR_LNMASK)) mvl = R[4] & STR_LNMASK;
if (((uint32) R[1]) < ((uint32) R[5])) { /* backward? */ if (((uint32) R[1]) < ((uint32) R[5])) { /* backward? */
while (R[2]) { /* loop thru char */ while (R[2]) { /* loop thru char */
t = Read ((R[1] + R[2] - 1) & LMASK, L_BYTE, RA); t = Read ((R[1] + R[2] - 1) & LMASK, L_BYTE, RA);
@ -177,17 +188,18 @@ switch (opc) { /* case on opcode */
R[2] = (R[2] - 1) & STR_LNMASK; R[2] = (R[2] - 1) & STR_LNMASK;
R[5] = (R[5] + 1) & LMASK; R[5] = (R[5] + 1) & LMASK;
} }
} } /* update lengths */
R[0] = (R[0] & ~STR_LNMASK) | ((R[0] - mvl) & STR_LNMASK); R[0] = (R[0] & ~STR_LNMASK) | ((R[0] - mvl) & STR_LNMASK);
R[4] = (R[4] - mvl) & STR_LNMASK; /* update lengths */ R[4] = (R[4] & ~STR_LNMASK) | ((R[4] - mvl) & STR_LNMASK);
} }
while (R[4]) { /* fill if needed */ while (R[4] & STR_LNMASK) { /* fill if needed */
Write (R[5], fill, L_BYTE, WA); Write (R[5], fill, L_BYTE, WA);
R[4] = (R[4] - 1) & STR_LNMASK; R[4] = (R[4] & ~STR_LNMASK) | ((R[4] - 1) & STR_LNMASK);
R[5] = (R[5] + 1) & LMASK; /* adv dst */ R[5] = (R[5] + 1) & LMASK; /* adv dst */
} }
R[0] = R[0] & STR_LNMASK; /* mask off state */ R[0] = R[0] & STR_LNMASK; /* mask off state */
PSL = PSL & ~PSL_FPD; /* all reg correct */ R[4] = 0;
PSL = PSL & ~PSL_FPD;
return cc; return cc;
/* MOVTUC /* MOVTUC
@ -201,7 +213,7 @@ switch (opc) { /* case on opcode */
Registers if PSL<fpd> = 1: Registers if PSL<fpd> = 1:
R[0] = delta-PC/match/source string length R[0] = delta-PC/match/source string length
R[1] = source string address R[1] = source string address
R[2] = not used R[2] = saved condition codes
R[3] = table address R[3] = table address
R[4] = destination string length R[4] = destination string length
R[5] = destination string address R[5] = destination string address
@ -224,24 +236,26 @@ switch (opc) { /* case on opcode */
SETPC (fault_PC + STR_GETDPC (R[0])); /* reset PC */ SETPC (fault_PC + STR_GETDPC (R[0])); /* reset PC */
fill = STR_GETCHR (R[0]); /* get match */ fill = STR_GETCHR (R[0]); /* get match */
R[4] = R[4] & STR_LNMASK; R[4] = R[4] & STR_LNMASK;
cc = R[2] & CC_MASK; /* restore cc's */
} }
else { else {
CC_CMP_W (op[0], op[4]); /* set cc's */
R[0] = STR_PACK (op[2], op[0]); /* src len, fill */ R[0] = STR_PACK (op[2], op[0]); /* src len, fill */
R[1] = op[1]; /* src addr */ R[1] = op[1]; /* src addr */
fill = op[2]; /* set match */ fill = op[2]; /* set match */
R[3] = op[3]; /* table addr */ R[3] = op[3]; /* table addr */
R[4] = op[4]; /* dst len */ R[4] = op[4]; /* dst len */
R[5] = op[5]; /* dst addr */ R[5] = op[5]; /* dst addr */
CC_CMP_W (op[0], op[4]); /* set cc's */ R[2] = cc; /* save cc's */
PSL = PSL | PSL_FPD; /* set FPD */ PSL = PSL | PSL_FPD; /* set FPD */
} }
while ((R[0] & STR_LNMASK) && R[4]) { /* while src & dst */ while ((R[0] & STR_LNMASK) && R[4]) { /* while src & dst */
t = Read (R[1], L_BYTE, RA); /* read src */ t = Read (R[1], L_BYTE, RA); /* read src */
if (t == fill) { /* stop char? */ c = Read ((R[3] + t) & LMASK, L_BYTE, RA); /* translate */
if (c == fill) { /* stop char? */
cc = cc | CC_V; /* set V, done */ cc = cc | CC_V; /* set V, done */
break; break;
} }
c = Read ((R[3] + t) & LMASK, L_BYTE, RA); /* translate */
Write (R[5], c, L_BYTE, WA); /* write dst */ Write (R[5], c, L_BYTE, WA); /* write dst */
R[0] = (R[0] & ~STR_LNMASK) | ((R[0] - 1) & STR_LNMASK); R[0] = (R[0] & ~STR_LNMASK) | ((R[0] - 1) & STR_LNMASK);
R[1] = (R[1] + 1) & LMASK; R[1] = (R[1] + 1) & LMASK;
@ -708,15 +722,17 @@ switch (opc) { /* case on opcode */
} /* end for */ } /* end for */
if (src1.sign) result = (~result + 1) & LMASK; /* negative? */ if (src1.sign) result = (~result + 1) & LMASK; /* negative? */
if (src1.sign ^ ((result & LSIGN) != 0)) V = 1; /* test for overflow */ if (src1.sign ^ ((result & LSIGN) != 0)) V = 1; /* test for overflow */
if (op[2] >= 0) R[op[2]] = result; if (op[2] < 0) /* if mem, store result */
else Write (op[3], result, L_LONG, WA); Write (op[3], result, L_LONG, WA); /* before reg update */
if (V && (PSL & PSW_IV)) SET_TRAP (TRAP_INTOV); /* ovflo and IV? trap */ R[0] = 0; /* update registers */
R[0] = 0;
R[1] = op[1]; R[1] = op[1];
R[2] = 0; R[2] = 0;
R[3] = 0; R[3] = 0;
if (op[2] >= 0) /* if reg, store result */
R[op[2]] = result; /* after reg update */
if (V && (PSL & PSW_IV)) SET_TRAP (TRAP_INTOV); /* ovflo and IV? trap */
CC_IIZZ_L (result); CC_IIZZ_L (result);
return cc | V; return cc | (V? CC_V: 0);
/* CVTLP /* CVTLP
@ -816,7 +832,8 @@ switch (opc) { /* case on opcode */
case CVTPS: case CVTPS:
if ((PSL & PSL_FPD) || (op[0] > 31) || (op[2] > 31)) if ((PSL & PSL_FPD) || (op[0] > 31) || (op[2] > 31))
RSVD_OPND_FAULT; RSVD_OPND_FAULT;
ReadDstr (op[0], op[1], &dst, acc); /* get src */ lenl = ReadDstr (op[0], op[1], &dst, acc); /* get source, lw len */
lenp = LntDstr (&dst, lenl); /* get exact nz src len */
ProbeDstr (op[2], op[3], WA); /* test dst write */ ProbeDstr (op[2], op[3], WA); /* test dst write */
Write (op[3], dst.sign? C_MINUS: C_PLUS, L_BYTE, WA); Write (op[3], dst.sign? C_MINUS: C_PLUS, L_BYTE, WA);
for (i = 1; i <= op[2]; i++) { /* loop thru chars */ for (i = 1; i <= op[2]; i++) { /* loop thru chars */
@ -824,7 +841,11 @@ switch (opc) { /* case on opcode */
c = d | C_ZERO; /* cvt to ASCII */ c = d | C_ZERO; /* cvt to ASCII */
Write ((op[3] + op[2] + 1 - i) & LMASK, c, L_BYTE, WA); Write ((op[3] + op[2] + 1 - i) & LMASK, c, L_BYTE, WA);
} }
cc = SetCCDstr (op[2], &dst, 0); /* set cc's */ cc = SetCCDstr (op[0], &dst, 0); /* set cc's */
if (lenp > op[2]) { /* src fit in dst? */
cc = cc | CC_V; /* set ovflo */
if (PSL & PSW_DV) SET_TRAP (TRAP_DECOVF); /* if enabled, trap */
}
R[0] = 0; R[0] = 0;
R[1] = op[1]; R[1] = op[1];
R[2] = 0; R[2] = 0;
@ -898,7 +919,8 @@ switch (opc) { /* case on opcode */
case CVTPT: case CVTPT:
if ((PSL & PSL_FPD) || (op[0] > 31) || (op[3] > 31)) if ((PSL & PSL_FPD) || (op[0] > 31) || (op[3] > 31))
RSVD_OPND_FAULT; RSVD_OPND_FAULT;
ReadDstr (op[0], op[1], &dst, acc); /* get source */ lenl = ReadDstr (op[0], op[1], &dst, acc); /* get source, lw len */
lenp = LntDstr (&dst, lenl); /* get exact src len */
ProbeDstr (op[3], op[4], WA); /* test writeability */ ProbeDstr (op[3], op[4], WA); /* test writeability */
for (i = 1; i <= op[3]; i++) { /* loop thru chars */ for (i = 1; i <= op[3]; i++) { /* loop thru chars */
if (i != 1) { /* not last? */ if (i != 1) { /* not last? */
@ -911,7 +933,11 @@ switch (opc) { /* case on opcode */
} }
Write ((op[4] + op[3] - i) & LMASK, c, L_BYTE, WA); Write ((op[4] + op[3] - i) & LMASK, c, L_BYTE, WA);
} }
cc = SetCCDstr (op[3], &dst, 0); /* set cc's */ cc = SetCCDstr (op[0], &dst, 0); /* set cc's from src */
if (lenp > op[3]) { /* src fit in dst? */
cc = cc | CC_V; /* set ovflo */
if (PSL & PSW_DV) SET_TRAP (TRAP_DECOVF); /* if enabled, trap */
}
R[0] = 0; R[0] = 0;
R[1] = op[1]; R[1] = op[1];
R[2] = 0; R[2] = 0;
@ -936,6 +962,7 @@ switch (opc) { /* case on opcode */
R0<15:0> = remaining source length R0<15:0> = remaining source length
R1 = source address R1 = source address
R2<31:24> = delta PC R2<31:24> = delta PC
R2<19:16> = condition codes
R2<15:8> = sign char R2<15:8> = sign char
R2<7:0> = fill char R2<7:0> = fill char
R3 = pattern string address R3 = pattern string address
@ -957,7 +984,7 @@ switch (opc) { /* case on opcode */
- It is safe to take a memory management fault on a write-only - It is safe to take a memory management fault on a write-only
operation, like fill. After correction of the fault, the operation, like fill. After correction of the fault, the
pattern operator is fetched and executed again. pattern operator is fetched and executed again.
- The move operators do not alter visible state (registers or cc) - The move operators do not alter visible state (registers or saved cc)
until all memory operations are complete. until all memory operations are complete.
*/ */
@ -966,6 +993,7 @@ switch (opc) { /* case on opcode */
SETPC (fault_PC + STR_GETDPC (R[2])); /* reset PC */ SETPC (fault_PC + STR_GETDPC (R[2])); /* reset PC */
fill = ED_GETFILL (R[2]); /* get fill */ fill = ED_GETFILL (R[2]); /* get fill */
sign = ED_GETSIGN (R[2]); /* get sign */ sign = ED_GETSIGN (R[2]); /* get sign */
cc = ED_GETCC (R[2]); /* get cc's */
R[0] = R[0] & ~0xFFE0; /* src len <= 31 */ R[0] = R[0] & ~0xFFE0; /* src len <= 31 */
} }
else { /* new instr */ else { /* new instr */
@ -982,12 +1010,13 @@ switch (opc) { /* case on opcode */
fill = C_SPACE; fill = C_SPACE;
R[0] = R[4] = op[0]; /* src len */ R[0] = R[4] = op[0]; /* src len */
R[1] = op[1]; /* src addr */ R[1] = op[1]; /* src addr */
R[2] = STR_PACK (0, (sign << ED_V_SIGN) | (fill << ED_V_FILL)); R[2] = STR_PACK (cc, (sign << ED_V_SIGN) | (fill << ED_V_FILL));
/* delta PC, sign, fill */ /* delta PC, cc, sign, fill */
R[3] = op[2]; /* pattern */ R[3] = op[2]; /* pattern */
R[5] = op[3]; /* dst addr */ R[5] = op[3]; /* dst addr */
PSL = PSL | PSL_FPD; /* set FPD */ PSL = PSL | PSL_FPD; /* set FPD */
} }
for ( ;; ) { /* loop thru pattern */ for ( ;; ) { /* loop thru pattern */
pop = Read (R[3], L_BYTE, RA); /* rd pattern op */ pop = Read (R[3], L_BYTE, RA); /* rd pattern op */
if (pop == EO_END) break; /* end? */ if (pop == EO_END) break; /* end? */
@ -997,6 +1026,7 @@ switch (opc) { /* case on opcode */
pop = pop & ~EO_RPT_MASK; /* isolate op */ pop = pop & ~EO_RPT_MASK; /* isolate op */
} }
switch (pop) { /* case on op */ switch (pop) { /* case on op */
case EO_END_FLOAT: /* end float */ case EO_END_FLOAT: /* end float */
if (!(cc & CC_C)) { /* not signif? */ if (!(cc & CC_C)) { /* not signif? */
Write (R[5], sign, L_BYTE, WA); /* write sign */ Write (R[5], sign, L_BYTE, WA); /* write sign */
@ -1004,43 +1034,59 @@ switch (opc) { /* case on opcode */
cc = cc | CC_C; /* set signif */ cc = cc | CC_C; /* set signif */
} }
break; break;
case EO_CLR_SIGNIF: /* clear signif */ case EO_CLR_SIGNIF: /* clear signif */
cc = cc & ~CC_C; /* clr C */ cc = cc & ~CC_C; /* clr C */
break; break;
case EO_SET_SIGNIF: /* set signif */ case EO_SET_SIGNIF: /* set signif */
cc = cc | CC_C; /* set C */ cc = cc | CC_C; /* set C */
break; break;
case EO_STORE_SIGN: /* store sign */ case EO_STORE_SIGN: /* store sign */
Write (R[5], sign, L_BYTE, WA); /* write sign */ Write (R[5], sign, L_BYTE, WA); /* write sign */
R[5] = (R[5] + 1) & LMASK; /* now fault safe */ R[5] = (R[5] + 1) & LMASK; /* now fault safe */
break; break;
case EO_LOAD_FILL: /* load fill */ case EO_LOAD_FILL: /* load fill */
fill = Read ((R[3] + 1) & LMASK, L_BYTE, RA); fill = Read ((R[3] + 1) & LMASK, L_BYTE, RA);
R[2] = ED_PUTFILL (R[2], fill); /* now fault safe */ R[2] = ED_PUTFILL (R[2], fill); /* now fault safe */
R[3]++; R[3]++;
break; break;
case EO_LOAD_SIGN: /* load sign */ case EO_LOAD_SIGN: /* load sign */
sign = edit_read_sign (acc); sign = edit_read_sign (acc);
R[3]++;
break; break;
case EO_LOAD_PLUS: /* load sign if + */ case EO_LOAD_PLUS: /* load sign if + */
if (!(cc & CC_N)) sign = edit_read_sign (acc); if (!(cc & CC_N)) sign = edit_read_sign (acc);
R[3]++;
break; break;
case EO_LOAD_MINUS: /* load sign if - */ case EO_LOAD_MINUS: /* load sign if - */
if (cc & CC_N) sign = edit_read_sign (acc); if (cc & CC_N) sign = edit_read_sign (acc);
R[3]++;
break; break;
case EO_INSERT: /* insert char */ case EO_INSERT: /* insert char */
c = Read ((R[3] + 1) & LMASK, L_BYTE, RA); c = Read ((R[3] + 1) & LMASK, L_BYTE, RA);
Write (R[5], ((cc & CC_C)? c: sign), L_BYTE, WA); Write (R[5], ((cc & CC_C)? c: fill), L_BYTE, WA);
R[5] = (R[5] + 1) & LMASK; /* now fault safe */ R[5] = (R[5] + 1) & LMASK; /* now fault safe */
R[3]++; R[3]++;
break; break;
case EO_BLANK_ZERO: /* blank zero */ case EO_BLANK_ZERO: /* blank zero */
t = Read ((R[3] + 1) & LMASK, L_BYTE, RA); t = Read ((R[3] + 1) & LMASK, L_BYTE, RA);
if (t == 0) RSVD_OPND_FAULT; if (t == 0) RSVD_OPND_FAULT;
while (t--) /* repeat and blank */ if (cc & CC_Z) { /* zero? */
Write ((R[5] - t) & LMASK, fill, L_BYTE, WA); do { /* repeat and blank */
Write ((R[5] - t) & LMASK, fill, L_BYTE, WA);
} while (--t);
}
R[3]++; /* now fault safe */ R[3]++; /* now fault safe */
break; break;
case EO_REPL_SIGN: /* replace sign */ case EO_REPL_SIGN: /* replace sign */
t = Read ((R[3] + 1) & LMASK, L_BYTE, RA); t = Read ((R[3] + 1) & LMASK, L_BYTE, RA);
if (t == 0) RSVD_OPND_FAULT; if (t == 0) RSVD_OPND_FAULT;
@ -1048,64 +1094,67 @@ switch (opc) { /* case on opcode */
Write ((R[5] - t) & LMASK, fill, L_BYTE, WA); Write ((R[5] - t) & LMASK, fill, L_BYTE, WA);
R[3]++; /* now fault safe */ R[3]++; /* now fault safe */
break; break;
case EO_ADJUST_LNT: /* adjust length */ case EO_ADJUST_LNT: /* adjust length */
t = Read ((R[3] + 1) & LMASK, L_BYTE, RA); t = Read ((R[3] + 1) & LMASK, L_BYTE, RA);
if ((t == 0) || (t > 31)) RSVD_OPND_FAULT; if ((t == 0) || (t > 31)) RSVD_OPND_FAULT;
R[0] = R[0] & WMASK; /* clr old ld zero */ R[0] = R[0] & WMASK; /* clr old ld zero */
if (R[0] > t) { /* decrease */ if (R[0] > t) { /* decrease */
ncc = cc; /* copy cc's */
for (i = 0; i < (R[0] - t); i++) { /* loop thru src */ for (i = 0; i < (R[0] - t); i++) { /* loop thru src */
d = edit_read_src (i, acc); /* get nibble */ d = edit_read_src (i, acc); /* get nibble */
if (d) ncc = (ncc | CC_V | CC_C) & ~CC_Z; if (d) cc = (cc | CC_V | CC_C) & ~CC_Z;
} /* end for */ } /* end for */
cc = ncc; /* now fault safe */
edit_adv_src (R[0] - t); /* adv src ptr */ edit_adv_src (R[0] - t); /* adv src ptr */
} /* end else */ } /* end else */
else R[0] = R[0] | (((R[0] - t) & WMASK) << 16); else R[0] = R[0] | (((R[0] - t) & WMASK) << 16);
R[3]++; R[3]++;
break; break;
case EO_FILL: /* fill */ case EO_FILL: /* fill */
for (i = 0; i < rpt; i++) /* fill string */ for (i = 0; i < rpt; i++) /* fill string */
Write ((R[5] + i) & LMASK, fill, L_BYTE, WA); Write ((R[5] + i) & LMASK, fill, L_BYTE, WA);
R[5] = (R[5] + rpt) & LMASK; /* now fault safe */ R[5] = (R[5] + rpt) & LMASK; /* now fault safe */
break; break;
case EO_MOVE: case EO_MOVE:
ncc = cc; /* copy cc's */
for (i = 0; i < rpt; i++) { /* for repeat */ for (i = 0; i < rpt; i++) { /* for repeat */
d = edit_read_src (i, acc); /* get nibble */ d = edit_read_src (i, acc); /* get nibble */
if (d) ncc = (ncc | CC_C) & ~CC_Z; /* test for non-zero */ if (d) cc = (cc | CC_C) & ~CC_Z; /* test for non-zero */
c = (ncc & CC_C)? (d | 0x30): fill; /* test for signif */ c = (cc & CC_C)? (d | 0x30): fill; /* test for signif */
Write ((R[5] + i) & LMASK, c, L_BYTE, WA); Write ((R[5] + i) & LMASK, c, L_BYTE, WA);
} /* end for */ } /* end for */
cc = ncc; /* now fault safe */
edit_adv_src (rpt); /* advance src */ edit_adv_src (rpt); /* advance src */
R[5] = (R[5] + rpt) & LMASK; /* advance dst */ R[5] = (R[5] + rpt) & LMASK; /* advance dst */
break; break;
case EO_FLOAT: case EO_FLOAT:
ncc = cc; /* copy cc's */
for (i = j = 0; i < rpt; i++, j++) { /* for repeat */ for (i = j = 0; i < rpt; i++, j++) { /* for repeat */
d = edit_read_src (i, acc); /* get nibble */ d = edit_read_src (i, acc); /* get nibble */
if (d && !(ncc & CC_C)) { /* nz, signif clear? */ if (d && !(cc & CC_C)) { /* nz, signif clear? */
Write ((R[5] + j) & LMASK, sign, L_BYTE, WA); Write ((R[5] + j) & LMASK, sign, L_BYTE, WA);
ncc = (ncc | CC_C) & ~CC_Z; /* set signif */ cc = (cc | CC_C) & ~CC_Z; /* set signif */
j++; /* extra dst char */ j++; /* extra dst char */
} /* end if */ } /* end if */
c = (ncc & CC_C)? (d | 0x30): fill; /* test for signif */ c = (cc & CC_C)? (d | 0x30): fill; /* test for signif */
Write ((R[5] + j) & LMASK, c, L_BYTE, WA); Write ((R[5] + j) & LMASK, c, L_BYTE, WA);
} /* end for */ } /* end for */
cc = ncc; /* now fault safe */
edit_adv_src (rpt); /* advance src */ edit_adv_src (rpt); /* advance src */
R[5] = (R[5] + j) & LMASK; /* advance dst */ R[5] = (R[5] + j) & LMASK; /* advance dst */
break; break;
default: /* undefined */ default: /* undefined */
RSVD_OPND_FAULT; RSVD_OPND_FAULT;
} /* end case pattern */ } /* end case pattern */
R[3] = (R[3] + 1) & LMASK; /* next pattern byte */ R[3] = (R[3] + 1) & LMASK; /* next pattern byte */
R[2] = ED_PUTCC (R[2], cc); /* update cc's */
} /* end for pattern */ } /* end for pattern */
if (R[0]) RSVD_OPND_FAULT; /* pattern too short */ if (R[0]) RSVD_OPND_FAULT; /* pattern too short */
PSL = PSL & ~PSL_FPD; /* clear FPD */ PSL = PSL & ~PSL_FPD; /* clear FPD */
if (cc & CC_Z) cc = cc & ~CC_N; /* zero? clear n */ if (cc & CC_Z) cc = cc & ~CC_N; /* zero? clear n */
if ((cc & CC_V) && (PSL & PSW_DV)) SET_TRAP (TRAP_DECOVF); if ((cc & CC_V) && (PSL & PSW_DV)) /* overflow & trap enabled? */
SET_TRAP (TRAP_DECOVF);
R[0] = R[4]; /* restore src len */ R[0] = R[4]; /* restore src len */
R[1] = R[1] - (R[0] >> 1); /* restore src addr */ R[1] = R[1] - (R[0] >> 1); /* restore src addr */
R[2] = R[4] = 0; R[2] = R[4] = 0;
@ -1146,8 +1195,8 @@ for (i = 0; i <= end; i++) { /* loop thru string */
c = c & 0xF0; /* erase sign */ c = c & 0xF0; /* erase sign */
} }
if ((i == end) && ((lnt & 1) == 0)) c = c & 0xF; if ((i == end) && ((lnt & 1) == 0)) c = c & 0xF;
if (((c & 0xF0) > 0x90) || /* check hi digit */ /* if (((c & 0xF0) > 0x90) || /* check hi digit */
((c & 0x0F) > 0x09)) RSVD_OPND_FAULT; /* check lo digit */ /* ((c & 0x0F) > 0x09)) RSVD_OPND_FAULT; /* check lo digit */
src->val[i / 4] = src->val[i / 4] | (c << ((i % 4) * 8)); src->val[i / 4] = src->val[i / 4] | (c << ((i % 4) * 8));
} /* end for */ } /* end for */
if ((t == 0xB) || (t == 0xD)) src->sign = 1; /* if -, set sign */ if ((t == 0xB) || (t == 0xD)) src->sign = 1; /* if -, set sign */
@ -1366,6 +1415,7 @@ int32 LntDstr (DSTR *dsrc, int32 nz)
{ {
int32 i; int32 i;
if (nz == 0) return 0;
for (i = 7; i > 0; i--) { for (i = 7; i > 0; i--) {
if ((dsrc->val[nz - 1] >> (i * 4)) & 0xF) break; if ((dsrc->val[nz - 1] >> (i * 4)) & 0xF) break;
} }
@ -1545,7 +1595,6 @@ int32 sign;
sign = Read ((R[3] + 1) & LMASK, L_BYTE, RA); /* read */ sign = Read ((R[3] + 1) & LMASK, L_BYTE, RA); /* read */
R[2] = ED_PUTSIGN (R[2], sign); /* now fault safe */ R[2] = ED_PUTSIGN (R[2], sign); /* now fault safe */
R[3] = (R[3] + 1) & LMASK;
return sign; return sign;
} }

View file

@ -1,6 +1,6 @@
/* vax_cmode.c: VAX compatibility mode /* vax_cmode.c: VAX compatibility mode
Copyright (c) 2004-2005, Robert M Supnik Copyright (c) 2004-2006, Robert M Supnik
Permission is hereby granted, free of charge, to any person obtaining a Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"), copy of this software and associated documentation files (the "Software"),
@ -26,6 +26,8 @@
On a full VAX, this module implements PDP-11 compatibility mode. On a full VAX, this module implements PDP-11 compatibility mode.
On a subset VAX, this module forces a fault if REI attempts to set PSL<cm>. On a subset VAX, this module forces a fault if REI attempts to set PSL<cm>.
03-May-06 RMS Fixed omission of SXT
Fixed order of operand fetching in XOR
24-Aug-04 RMS Cloned from PDP-11 CPU 24-Aug-04 RMS Cloned from PDP-11 CPU
In compatibility mode, the Istream prefetch mechanism is not used. The In compatibility mode, the Istream prefetch mechanism is not used. The
@ -113,9 +115,11 @@ switch ((IR >> 12) & 017) { /* decode IR<15:12> */
case 3: /* BPT */ case 3: /* BPT */
CMODE_FAULT (CMODE_BPT); CMODE_FAULT (CMODE_BPT);
break; break;
case 4: /* IOT */ case 4: /* IOT */
CMODE_FAULT (CMODE_IOT); CMODE_FAULT (CMODE_IOT);
break; break;
case 2: /* RTI */ case 2: /* RTI */
case 6: /* RTT */ case 6: /* RTT */
src = RdMemW (R[6] & WMASK); /* new PC */ src = RdMemW (R[6] & WMASK); /* new PC */
@ -126,15 +130,18 @@ switch ((IR >> 12) & 017) { /* decode IR<15:12> */
else PSL = PSL & ~PSW_T; else PSL = PSL & ~PSW_T;
CMODE_JUMP (src); /* update PC */ CMODE_JUMP (src); /* update PC */
break; break;
default: /* undefined */ default: /* undefined */
CMODE_FAULT (CMODE_RSVI); CMODE_FAULT (CMODE_RSVI);
break; break;
} /* end switch IR */ } /* end switch IR */
break; /* end case 0000xx */ break; /* end case 0000xx */
case 001: /* JMP */ case 001: /* JMP */
if (dstreg) CMODE_FAULT (CMODE_ILLI); /* mode 0 illegal */ if (dstreg) CMODE_FAULT (CMODE_ILLI); /* mode 0 illegal */
else { CMODE_JUMP (GeteaW (dstspec)); } else { CMODE_JUMP (GeteaW (dstspec)); }
break; break;
case 002: /* 0002xx */ case 002: /* 0002xx */
if (IR < 000210) { /* RTS */ if (IR < 000210) { /* RTS */
dstspec = dstspec & 07; dstspec = dstspec & 07;
@ -153,6 +160,7 @@ switch ((IR >> 12) & 017) { /* decode IR<15:12> */
if (IR < 000260) cc = cc & ~(IR & CC_MASK); /* clear CC */ if (IR < 000260) cc = cc & ~(IR & CC_MASK); /* clear CC */
else cc = cc | (IR & CC_MASK); /* set CC */ else cc = cc | (IR & CC_MASK); /* set CC */
break; break;
case 003: /* SWAB */ case 003: /* SWAB */
if (dstreg) src = RdRegW (dstspec); if (dstreg) src = RdRegW (dstspec);
else src = RdMemMW (ea = GeteaW (dstspec)); else src = RdMemMW (ea = GeteaW (dstspec));
@ -161,48 +169,63 @@ switch ((IR >> 12) & 017) { /* decode IR<15:12> */
else WrMemW (dst, ea); else WrMemW (dst, ea);
CC_IIZZ_B ((dst & BMASK)); CC_IIZZ_B ((dst & BMASK));
break; break;
case 004: case 005: /* BR */ case 004: case 005: /* BR */
BRANCH_F (IR); BRANCH_F (IR);
break; break;
case 006: case 007: /* BR */ case 006: case 007: /* BR */
BRANCH_B (IR); BRANCH_B (IR);
break; break;
case 010: case 011: /* BNE */ case 010: case 011: /* BNE */
if ((cc & CC_Z) == 0) { BRANCH_F (IR); } if ((cc & CC_Z) == 0) { BRANCH_F (IR); }
break; break;
case 012: case 013: /* BNE */ case 012: case 013: /* BNE */
if ((cc & CC_Z) == 0) { BRANCH_B (IR); } if ((cc & CC_Z) == 0) { BRANCH_B (IR); }
break; break;
case 014: case 015: /* BEQ */ case 014: case 015: /* BEQ */
if (cc & CC_Z) { BRANCH_F (IR); } if (cc & CC_Z) { BRANCH_F (IR); }
break; break;
case 016: case 017: /* BEQ */ case 016: case 017: /* BEQ */
if (cc & CC_Z) { BRANCH_B (IR); } if (cc & CC_Z) { BRANCH_B (IR); }
break; break;
case 020: case 021: /* BGE */ case 020: case 021: /* BGE */
if (CC_XOR_NV (cc) == 0) { BRANCH_F (IR); } if (CC_XOR_NV (cc) == 0) { BRANCH_F (IR); }
break; break;
case 022: case 023: /* BGE */ case 022: case 023: /* BGE */
if (CC_XOR_NV (cc) == 0) { BRANCH_B (IR); } if (CC_XOR_NV (cc) == 0) { BRANCH_B (IR); }
break; break;
case 024: case 025: /* BLT */ case 024: case 025: /* BLT */
if (CC_XOR_NV (cc)) { BRANCH_F (IR); } if (CC_XOR_NV (cc)) { BRANCH_F (IR); }
break; break;
case 026: case 027: /* BLT */ case 026: case 027: /* BLT */
if (CC_XOR_NV (cc)) { BRANCH_B (IR); } if (CC_XOR_NV (cc)) { BRANCH_B (IR); }
break; break;
case 030: case 031: /* BGT */ case 030: case 031: /* BGT */
if (((cc & CC_Z) || CC_XOR_NV (cc)) == 0) { BRANCH_F (IR); } if (((cc & CC_Z) || CC_XOR_NV (cc)) == 0) { BRANCH_F (IR); }
break; break;
case 032: case 033: /* BGT */ case 032: case 033: /* BGT */
if (((cc & CC_Z) || CC_XOR_NV (cc)) == 0) { BRANCH_B (IR); } if (((cc & CC_Z) || CC_XOR_NV (cc)) == 0) { BRANCH_B (IR); }
break; break;
case 034: case 035: /* BLE */ case 034: case 035: /* BLE */
if ((cc & CC_Z) || CC_XOR_NV (cc)) { BRANCH_F (IR); } if ((cc & CC_Z) || CC_XOR_NV (cc)) { BRANCH_F (IR); }
break; break;
case 036: case 037: /* BLE */ case 036: case 037: /* BLE */
if ((cc & CC_Z) || CC_XOR_NV (cc)) { BRANCH_B (IR); } if ((cc & CC_Z) || CC_XOR_NV (cc)) { BRANCH_B (IR); }
break; break;
case 040: case 041: case 042: case 043: /* JSR */ case 040: case 041: case 042: case 043: /* JSR */
case 044: case 045: case 046: case 047: case 044: case 045: case 046: case 047:
if (dstreg) CMODE_FAULT (CMODE_ILLI); /* mode 0 illegal */ if (dstreg) CMODE_FAULT (CMODE_ILLI); /* mode 0 illegal */
@ -216,11 +239,13 @@ switch ((IR >> 12) & 017) { /* decode IR<15:12> */
CMODE_JUMP (dst); /* PC <- dst */ CMODE_JUMP (dst); /* PC <- dst */
} }
break; /* end JSR */ break; /* end JSR */
case 050: /* CLR */ case 050: /* CLR */
if (dstreg) WrRegW (0, dstspec); if (dstreg) WrRegW (0, dstspec);
else WrMemW (0, GeteaW (dstspec)); else WrMemW (0, GeteaW (dstspec));
cc = CC_Z; cc = CC_Z;
break; break;
case 051: /* COM */ case 051: /* COM */
if (dstreg) src = RdRegW (dstspec); if (dstreg) src = RdRegW (dstspec);
else src = RdMemMW (ea = GeteaW (dstspec)); else src = RdMemMW (ea = GeteaW (dstspec));
@ -230,6 +255,7 @@ switch ((IR >> 12) & 017) { /* decode IR<15:12> */
CC_IIZZ_W (dst); CC_IIZZ_W (dst);
cc = cc | CC_C; cc = cc | CC_C;
break; break;
case 052: /* INC */ case 052: /* INC */
if (dstreg) src = RdRegW (dstspec); if (dstreg) src = RdRegW (dstspec);
else src = RdMemMW (ea = GeteaW (dstspec)); else src = RdMemMW (ea = GeteaW (dstspec));
@ -239,6 +265,7 @@ switch ((IR >> 12) & 017) { /* decode IR<15:12> */
CC_IIZP_W (dst); CC_IIZP_W (dst);
if (dst == 0100000) cc = cc | CC_V; if (dst == 0100000) cc = cc | CC_V;
break; break;
case 053: /* DEC */ case 053: /* DEC */
if (dstreg) src = RdRegW (dstspec); if (dstreg) src = RdRegW (dstspec);
else src = RdMemMW (ea = GeteaW (dstspec)); else src = RdMemMW (ea = GeteaW (dstspec));
@ -248,6 +275,7 @@ switch ((IR >> 12) & 017) { /* decode IR<15:12> */
CC_IIZP_W (dst); CC_IIZP_W (dst);
if (dst == 077777) cc = cc | CC_V; if (dst == 077777) cc = cc | CC_V;
break; break;
case 054: /* NEG */ case 054: /* NEG */
if (dstreg) src = RdRegW (dstspec); if (dstreg) src = RdRegW (dstspec);
else src = RdMemMW (ea = GeteaW (dstspec)); else src = RdMemMW (ea = GeteaW (dstspec));
@ -258,6 +286,7 @@ switch ((IR >> 12) & 017) { /* decode IR<15:12> */
if (dst == 0100000) cc = cc | CC_V; if (dst == 0100000) cc = cc | CC_V;
if (dst) cc = cc | CC_C; if (dst) cc = cc | CC_C;
break; break;
case 055: /* ADC */ case 055: /* ADC */
if (dstreg) src = RdRegW (dstspec); if (dstreg) src = RdRegW (dstspec);
else src = RdMemMW (ea = GeteaW (dstspec)); else src = RdMemMW (ea = GeteaW (dstspec));
@ -268,6 +297,7 @@ switch ((IR >> 12) & 017) { /* decode IR<15:12> */
if ((src == 077777) && (dst == 0100000)) cc = cc | CC_V; if ((src == 077777) && (dst == 0100000)) cc = cc | CC_V;
if ((src == 0177777) && (dst == 0)) cc = cc | CC_C; if ((src == 0177777) && (dst == 0)) cc = cc | CC_C;
break; break;
case 056: /* SBC */ case 056: /* SBC */
if (dstreg) src = RdRegW (dstspec); if (dstreg) src = RdRegW (dstspec);
else src = RdMemMW (ea = GeteaW (dstspec)); else src = RdMemMW (ea = GeteaW (dstspec));
@ -278,11 +308,13 @@ switch ((IR >> 12) & 017) { /* decode IR<15:12> */
if ((src == 0100000) && (dst == 077777)) cc = cc | CC_V; if ((src == 0100000) && (dst == 077777)) cc = cc | CC_V;
if ((src == 0) && (dst == 0177777)) cc = cc | CC_C; if ((src == 0) && (dst == 0177777)) cc = cc | CC_C;
break; break;
case 057: /* TST */ case 057: /* TST */
if (dstreg) src = RdRegW (dstspec); if (dstreg) src = RdRegW (dstspec);
else src = RdMemW (GeteaW (dstspec)); else src = RdMemW (GeteaW (dstspec));
CC_IIZZ_W (src); CC_IIZZ_W (src);
break; break;
case 060: /* ROR */ case 060: /* ROR */
if (dstreg) src = RdRegW (dstspec); if (dstreg) src = RdRegW (dstspec);
else src = RdMemMW (ea = GeteaW (dstspec)); else src = RdMemMW (ea = GeteaW (dstspec));
@ -293,6 +325,7 @@ switch ((IR >> 12) & 017) { /* decode IR<15:12> */
if (src & 1) cc = cc | CC_C; if (src & 1) cc = cc | CC_C;
if (CC_XOR_NC (cc)) cc = cc | CC_V; if (CC_XOR_NC (cc)) cc = cc | CC_V;
break; break;
case 061: /* ROL */ case 061: /* ROL */
if (dstreg) src = RdRegW (dstspec); if (dstreg) src = RdRegW (dstspec);
else src = RdMemMW (ea = GeteaW (dstspec)); else src = RdMemMW (ea = GeteaW (dstspec));
@ -303,6 +336,7 @@ switch ((IR >> 12) & 017) { /* decode IR<15:12> */
if (src & WSIGN) cc = cc | CC_C; if (src & WSIGN) cc = cc | CC_C;
if (CC_XOR_NC (cc)) cc = cc | CC_V; if (CC_XOR_NC (cc)) cc = cc | CC_V;
break; break;
case 062: /* ASR */ case 062: /* ASR */
if (dstreg) src = RdRegW (dstspec); if (dstreg) src = RdRegW (dstspec);
else src = RdMemMW (ea = GeteaW (dstspec)); else src = RdMemMW (ea = GeteaW (dstspec));
@ -313,6 +347,7 @@ switch ((IR >> 12) & 017) { /* decode IR<15:12> */
if (src & 1) cc = cc | CC_C; if (src & 1) cc = cc | CC_C;
if (CC_XOR_NC (cc)) cc = cc | CC_V; if (CC_XOR_NC (cc)) cc = cc | CC_V;
break; break;
case 063: /* ASL */ case 063: /* ASL */
if (dstreg) src = RdRegW (dstspec); if (dstreg) src = RdRegW (dstspec);
else src = RdMemMW (ea = GeteaW (dstspec)); else src = RdMemMW (ea = GeteaW (dstspec));
@ -323,6 +358,7 @@ switch ((IR >> 12) & 017) { /* decode IR<15:12> */
if (src & WSIGN) cc = cc | CC_C; if (src & WSIGN) cc = cc | CC_C;
if (CC_XOR_NC (cc)) cc = cc | CC_V; if (CC_XOR_NC (cc)) cc = cc | CC_V;
break; break;
case 065: /* MFPI */ case 065: /* MFPI */
if (dstreg) dst = RdRegW (dstspec); /* "mov dst,-(sp)" */ if (dstreg) dst = RdRegW (dstspec); /* "mov dst,-(sp)" */
else dst = RdMemW (GeteaW (dstspec)); else dst = RdMemW (GeteaW (dstspec));
@ -330,6 +366,7 @@ switch ((IR >> 12) & 017) { /* decode IR<15:12> */
R[6] = (R[6] - 2) & WMASK; R[6] = (R[6] - 2) & WMASK;
CC_IIZP_W (dst); CC_IIZP_W (dst);
break; break;
case 066: /* MTPI */ case 066: /* MTPI */
dst = RdMemW (R[6] & WMASK); /* "mov (sp)+,dst" */ dst = RdMemW (R[6] & WMASK); /* "mov (sp)+,dst" */
R[6] = (R[6] + 2) & WMASK; R[6] = (R[6] + 2) & WMASK;
@ -338,6 +375,14 @@ switch ((IR >> 12) & 017) { /* decode IR<15:12> */
else WrMemW (dst, (GeteaW (dstspec) & WMASK)); else WrMemW (dst, (GeteaW (dstspec) & WMASK));
CC_IIZP_W (dst); CC_IIZP_W (dst);
break; break;
case 067: /* SXT */
dst = (cc & CC_N)? 0177777: 0;
if (dstreg) WrRegW (dst, dstspec);
else WrMemW (dst, GeteaW (dstspec));
CC_IIZP_W (dst);
break;
default: /* undefined */ default: /* undefined */
CMODE_FAULT (CMODE_RSVI); CMODE_FAULT (CMODE_RSVI);
break; break;
@ -538,9 +583,9 @@ switch ((IR >> 12) & 017) { /* decode IR<15:12> */
break; break;
case 4: /* XOR */ case 4: /* XOR */
src = RdRegW (srcspec); /* get src */
if (dstreg) src2 = RdRegW (dstspec); /* get dst */ if (dstreg) src2 = RdRegW (dstspec); /* get dst */
else src2 = RdMemMW (ea = GeteaW (dstspec)); else src2 = RdMemMW (ea = GeteaW (dstspec));
src = RdRegW (srcspec); /* get src */
dst = src2 ^ src; dst = src2 ^ src;
if (dstreg) WrRegW (dst, dstspec); /* result */ if (dstreg) WrRegW (dst, dstspec); /* result */
else WrMemW (dst, ea); else WrMemW (dst, ea);
@ -567,62 +612,81 @@ switch ((IR >> 12) & 017) { /* decode IR<15:12> */
case 000: case 001: /* BPL */ case 000: case 001: /* BPL */
if ((cc & CC_N) == 0) { BRANCH_F (IR); } if ((cc & CC_N) == 0) { BRANCH_F (IR); }
break; break;
case 002: case 003: /* BPL */ case 002: case 003: /* BPL */
if ((cc & CC_N) == 0) { BRANCH_B (IR); } if ((cc & CC_N) == 0) { BRANCH_B (IR); }
break; break;
case 004: case 005: /* BMI */ case 004: case 005: /* BMI */
if (cc & CC_N) { BRANCH_F (IR); } if (cc & CC_N) { BRANCH_F (IR); }
break; break;
case 006: case 007: /* BMI */ case 006: case 007: /* BMI */
if (cc & CC_N) { BRANCH_B (IR); } if (cc & CC_N) { BRANCH_B (IR); }
break; break;
case 010: case 011: /* BHI */ case 010: case 011: /* BHI */
if ((cc & (CC_C | CC_Z)) == 0) { BRANCH_F (IR); } if ((cc & (CC_C | CC_Z)) == 0) { BRANCH_F (IR); }
break; break;
case 012: case 013: /* BHI */ case 012: case 013: /* BHI */
if ((cc & (CC_C | CC_Z)) == 0) { BRANCH_B (IR); } if ((cc & (CC_C | CC_Z)) == 0) { BRANCH_B (IR); }
break; break;
case 014: case 015: /* BLOS */ case 014: case 015: /* BLOS */
if (cc & (CC_C | CC_Z)) { BRANCH_F (IR); } if (cc & (CC_C | CC_Z)) { BRANCH_F (IR); }
break; break;
case 016: case 017: /* BLOS */ case 016: case 017: /* BLOS */
if (cc & (CC_C | CC_Z)) { BRANCH_B (IR); } if (cc & (CC_C | CC_Z)) { BRANCH_B (IR); }
break; break;
case 020: case 021: /* BVC */ case 020: case 021: /* BVC */
if ((cc & CC_V) == 0) { BRANCH_F (IR); } if ((cc & CC_V) == 0) { BRANCH_F (IR); }
break; break;
case 022: case 023: /* BVC */ case 022: case 023: /* BVC */
if ((cc & CC_V) == 0) { BRANCH_B (IR); } if ((cc & CC_V) == 0) { BRANCH_B (IR); }
break; break;
case 024: case 025: /* BVS */ case 024: case 025: /* BVS */
if (cc & CC_V) { BRANCH_F (IR); } if (cc & CC_V) { BRANCH_F (IR); }
break; break;
case 026: case 027: /* BVS */ case 026: case 027: /* BVS */
if (cc & CC_V) { BRANCH_B (IR); } if (cc & CC_V) { BRANCH_B (IR); }
break; break;
case 030: case 031: /* BCC */ case 030: case 031: /* BCC */
if ((cc & CC_C) == 0) { BRANCH_F (IR); } if ((cc & CC_C) == 0) { BRANCH_F (IR); }
break; break;
case 032: case 033: /* BCC */ case 032: case 033: /* BCC */
if ((cc & CC_C) == 0) { BRANCH_B (IR); } if ((cc & CC_C) == 0) { BRANCH_B (IR); }
break; break;
case 034: case 035: /* BCS */ case 034: case 035: /* BCS */
if (cc & CC_C) { BRANCH_F (IR); } if (cc & CC_C) { BRANCH_F (IR); }
break; break;
case 036: case 037: /* BCS */ case 036: case 037: /* BCS */
if (cc & CC_C) { BRANCH_B (IR); } if (cc & CC_C) { BRANCH_B (IR); }
break; break;
case 040: case 041: case 042: case 043: /* EMT */ case 040: case 041: case 042: case 043: /* EMT */
CMODE_FAULT (CMODE_EMT); CMODE_FAULT (CMODE_EMT);
break; break;
case 044: case 045: case 046: case 047: /* TRAP */ case 044: case 045: case 046: case 047: /* TRAP */
CMODE_FAULT (CMODE_TRAP); CMODE_FAULT (CMODE_TRAP);
break; break;
case 050: /* CLRB */ case 050: /* CLRB */
if (dstreg) WrRegB (0, dstspec); if (dstreg) WrRegB (0, dstspec);
else WrMemB (0, GeteaB (dstspec)); else WrMemB (0, GeteaB (dstspec));
cc = CC_Z; cc = CC_Z;
break; break;
case 051: /* COMB */ case 051: /* COMB */
if (dstreg) src = RdRegB (dstspec); if (dstreg) src = RdRegB (dstspec);
else src = RdMemMB (ea = GeteaB (dstspec)); else src = RdMemMB (ea = GeteaB (dstspec));
@ -632,6 +696,7 @@ switch ((IR >> 12) & 017) { /* decode IR<15:12> */
CC_IIZZ_B (dst); CC_IIZZ_B (dst);
cc = cc | CC_C; cc = cc | CC_C;
break; break;
case 052: /* INCB */ case 052: /* INCB */
if (dstreg) src = RdRegB (dstspec); if (dstreg) src = RdRegB (dstspec);
else src = RdMemMB (ea = GeteaB (dstspec)); else src = RdMemMB (ea = GeteaB (dstspec));
@ -641,6 +706,7 @@ switch ((IR >> 12) & 017) { /* decode IR<15:12> */
CC_IIZP_B (dst); CC_IIZP_B (dst);
if (dst == 0200) cc = cc | CC_V; if (dst == 0200) cc = cc | CC_V;
break; break;
case 053: /* DECB */ case 053: /* DECB */
if (dstreg) src = RdRegB (dstspec); if (dstreg) src = RdRegB (dstspec);
else src = RdMemMB (ea = GeteaB (dstspec)); else src = RdMemMB (ea = GeteaB (dstspec));
@ -650,6 +716,7 @@ switch ((IR >> 12) & 017) { /* decode IR<15:12> */
CC_IIZP_B (dst); CC_IIZP_B (dst);
if (dst == 0177) cc = cc | CC_V; if (dst == 0177) cc = cc | CC_V;
break; break;
case 054: /* NEGB */ case 054: /* NEGB */
if (dstreg) src = RdRegB (dstspec); if (dstreg) src = RdRegB (dstspec);
else src = RdMemMB (ea = GeteaB (dstspec)); else src = RdMemMB (ea = GeteaB (dstspec));
@ -660,6 +727,7 @@ switch ((IR >> 12) & 017) { /* decode IR<15:12> */
if (dst == 0200) cc = cc | CC_V; if (dst == 0200) cc = cc | CC_V;
if (dst) cc = cc | CC_C; if (dst) cc = cc | CC_C;
break; break;
case 055: /* ADCB */ case 055: /* ADCB */
if (dstreg) src = RdRegB (dstspec); if (dstreg) src = RdRegB (dstspec);
else src = RdMemMB (ea = GeteaB (dstspec)); else src = RdMemMB (ea = GeteaB (dstspec));
@ -670,6 +738,7 @@ switch ((IR >> 12) & 017) { /* decode IR<15:12> */
if ((src == 0177) && (dst == 0200)) cc = cc | CC_V; if ((src == 0177) && (dst == 0200)) cc = cc | CC_V;
if ((src == 0377) && (dst == 0)) cc = cc | CC_C; if ((src == 0377) && (dst == 0)) cc = cc | CC_C;
break; break;
case 056: /* SBCB */ case 056: /* SBCB */
if (dstreg) src = RdRegB (dstspec); if (dstreg) src = RdRegB (dstspec);
else src = RdMemMB (ea = GeteaB (dstspec)); else src = RdMemMB (ea = GeteaB (dstspec));
@ -680,11 +749,13 @@ switch ((IR >> 12) & 017) { /* decode IR<15:12> */
if ((src == 0200) && (dst == 0177)) cc = cc | CC_V; if ((src == 0200) && (dst == 0177)) cc = cc | CC_V;
if ((src == 0) && (dst == 0377)) cc = cc | CC_C; if ((src == 0) && (dst == 0377)) cc = cc | CC_C;
break; break;
case 057: /* TSTB */ case 057: /* TSTB */
if (dstreg) src = RdRegB (dstspec); if (dstreg) src = RdRegB (dstspec);
else src = RdMemB (GeteaB (dstspec)); else src = RdMemB (GeteaB (dstspec));
CC_IIZZ_B (src); CC_IIZZ_B (src);
break; break;
case 060: /* RORB */ case 060: /* RORB */
if (dstreg) src = RdRegB (dstspec); if (dstreg) src = RdRegB (dstspec);
else src = RdMemMB (ea = GeteaB (dstspec)); else src = RdMemMB (ea = GeteaB (dstspec));
@ -695,6 +766,7 @@ switch ((IR >> 12) & 017) { /* decode IR<15:12> */
if (src & 1) cc = cc | CC_C; if (src & 1) cc = cc | CC_C;
if (CC_XOR_NC (cc)) cc = cc | CC_V; if (CC_XOR_NC (cc)) cc = cc | CC_V;
break; break;
case 061: /* ROLB */ case 061: /* ROLB */
if (dstreg) src = RdRegB (dstspec); if (dstreg) src = RdRegB (dstspec);
else src = RdMemMB (ea = GeteaB (dstspec)); else src = RdMemMB (ea = GeteaB (dstspec));
@ -705,6 +777,7 @@ switch ((IR >> 12) & 017) { /* decode IR<15:12> */
if (src & BSIGN) cc = cc | CC_C; if (src & BSIGN) cc = cc | CC_C;
if (CC_XOR_NC (cc)) cc = cc | CC_V; if (CC_XOR_NC (cc)) cc = cc | CC_V;
break; break;
case 062: /* ASRB */ case 062: /* ASRB */
if (dstreg) src = RdRegB (dstspec); if (dstreg) src = RdRegB (dstspec);
else src = RdMemMB (ea = GeteaB (dstspec)); else src = RdMemMB (ea = GeteaB (dstspec));
@ -715,6 +788,7 @@ switch ((IR >> 12) & 017) { /* decode IR<15:12> */
if (src & 1) cc = cc | CC_C; if (src & 1) cc = cc | CC_C;
if (CC_XOR_NC (cc)) cc = cc | CC_V; if (CC_XOR_NC (cc)) cc = cc | CC_V;
break; break;
case 063: /* ASLB */ case 063: /* ASLB */
if (dstreg) src = RdRegB (dstspec); if (dstreg) src = RdRegB (dstspec);
else src = RdMemMB (ea = GeteaB (dstspec)); else src = RdMemMB (ea = GeteaB (dstspec));
@ -725,6 +799,7 @@ switch ((IR >> 12) & 017) { /* decode IR<15:12> */
if (src & BSIGN) cc = cc | CC_C; if (src & BSIGN) cc = cc | CC_C;
if (CC_XOR_NC (cc)) cc = cc | CC_V; if (CC_XOR_NC (cc)) cc = cc | CC_V;
break; break;
case 065: /* MFPD */ case 065: /* MFPD */
if (dstreg) dst = RdRegW (dstspec); /* "mov dst,-(sp)" */ if (dstreg) dst = RdRegW (dstspec); /* "mov dst,-(sp)" */
else dst = RdMemW (GeteaW (dstspec)); else dst = RdMemW (GeteaW (dstspec));
@ -732,6 +807,7 @@ switch ((IR >> 12) & 017) { /* decode IR<15:12> */
R[6] = (R[6] - 2) & WMASK; R[6] = (R[6] - 2) & WMASK;
CC_IIZP_W (dst); CC_IIZP_W (dst);
break; break;
case 066: /* MTPD */ case 066: /* MTPD */
dst = RdMemW (R[6] & WMASK); /* "mov (sp)+,dst" */ dst = RdMemW (R[6] & WMASK); /* "mov (sp)+,dst" */
R[6] = (R[6] + 2) & WMASK; R[6] = (R[6] + 2) & WMASK;
@ -740,6 +816,7 @@ switch ((IR >> 12) & 017) { /* decode IR<15:12> */
else WrMemW (dst, (GeteaW (dstspec) & WMASK)); else WrMemW (dst, (GeteaW (dstspec) & WMASK));
CC_IIZP_W (dst); CC_IIZP_W (dst);
break; break;
default: default:
CMODE_FAULT (CMODE_RSVI); CMODE_FAULT (CMODE_RSVI);
break; } /* end switch SOPs */ break; } /* end switch SOPs */

View file

@ -1,6 +1,6 @@
/* vax_cpu.c: VAX CPU /* vax_cpu.c: VAX CPU
Copyright (c) 1998-2005, Robert M Supnik Copyright (c) 1998-2006, Robert M Supnik
Permission is hereby granted, free of charge, to any person obtaining a Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"), copy of this software and associated documentation files (the "Software"),
@ -25,6 +25,17 @@
cpu VAX central processor cpu VAX central processor
22-May-06 RMS Fixed format error in CPU history (found by Peter Schorn)
10-May-06 RMS Added -kesu switches for virtual addressing modes
Fixed bugs in examine virtual
Rewrote history function for greater usability
Fixed bug in reported VA on faulting cross-page write
02-May-06 RMS Fixed fault cleanup to clear PSL<tp>
Fixed ADAWI r-mode to preserve dst<31:16>
Fixed ACBD/G to test correct operand
Fixed access checking on modify-class specifiers
Fixed branch displacements in history buffer
(all reported by Tim Stark)
17-Nov-05 RMS Fixed CVTfi with integer overflow to trap if PSW<iv> set 17-Nov-05 RMS Fixed CVTfi with integer overflow to trap if PSW<iv> set
13-Nov-05 RMS Fixed breakpoint test with 64b addresses 13-Nov-05 RMS Fixed breakpoint test with 64b addresses
25-Oct-05 RMS Removed cpu_extmem 25-Oct-05 RMS Removed cpu_extmem
@ -158,7 +169,8 @@
#define UNIT_MSIZE (1u << UNIT_V_MSIZE) #define UNIT_MSIZE (1u << UNIT_V_MSIZE)
#define GET_CUR acc = ACC_MASK (PSL_GETCUR (PSL)) #define GET_CUR acc = ACC_MASK (PSL_GETCUR (PSL))
#define OPND_SIZE 20 #define OPND_SIZE 16
#define INST_SIZE 52
#define op0 opnd[0] #define op0 opnd[0]
#define op1 opnd[1] #define op1 opnd[1]
#define op2 opnd[2] #define op2 opnd[2]
@ -178,7 +190,8 @@
#define WRITE_L(r) if (spec > (GRN | nPC)) Write (va, r, L_LONG, WA); \ #define WRITE_L(r) if (spec > (GRN | nPC)) Write (va, r, L_LONG, WA); \
else R[rn] = (r) else R[rn] = (r)
#define WRITE_Q(rl,rh) if (spec > (GRN | nPC)) { \ #define WRITE_Q(rl,rh) if (spec > (GRN | nPC)) { \
if (Test (va + 7, WA, &mstat) >= 0) \ if ((Test (va + 7, WA, &mstat) >= 0) || \
(Test (va, WA, &mstat) < 0)) \
Write (va, rl, L_LONG, WA); \ Write (va, rl, L_LONG, WA); \
Write (va + 4, rh, L_LONG, WA); \ Write (va + 4, rh, L_LONG, WA); \
} \ } \
@ -195,7 +208,7 @@ typedef struct {
int32 iPC; int32 iPC;
int32 PSL; int32 PSL;
int32 opc; int32 opc;
int32 brdest; uint8 inst[INST_SIZE];
int32 opnd[OPND_SIZE]; int32 opnd[OPND_SIZE];
} InstHistory; } InstHistory;
@ -265,6 +278,7 @@ const uint32 align[4] = {
extern int32 sim_interval; extern int32 sim_interval;
extern int32 sim_int_char; extern int32 sim_int_char;
extern int32 sim_switches;
extern uint32 sim_brk_types, sim_brk_dflt, sim_brk_summ; /* breakpoint info */ extern uint32 sim_brk_types, sim_brk_dflt, sim_brk_summ; /* breakpoint info */
extern UNIT clk_unit; extern UNIT clk_unit;
@ -353,8 +367,10 @@ t_stat cpu_set_size (UNIT *uptr, int32 val, char *cptr, void *desc);
t_stat cpu_set_hist (UNIT *uptr, int32 val, char *cptr, void *desc); t_stat cpu_set_hist (UNIT *uptr, int32 val, char *cptr, void *desc);
t_stat cpu_show_hist (FILE *st, UNIT *uptr, int32 val, void *desc); t_stat cpu_show_hist (FILE *st, UNIT *uptr, int32 val, void *desc);
t_stat cpu_show_virt (FILE *st, UNIT *uptr, int32 val, void *desc); t_stat cpu_show_virt (FILE *st, UNIT *uptr, int32 val, void *desc);
int32 cpu_get_vsw (int32 sw);
int32 get_istr (int32 lnt, int32 acc); int32 get_istr (int32 lnt, int32 acc);
int32 ReadOcta (int32 va, int32 *opnd, int32 j, int32 acc); int32 ReadOcta (int32 va, int32 *opnd, int32 j, int32 acc);
t_bool cpu_show_opnd (FILE *st, InstHistory *h, int32 line);
/* CPU data structures /* CPU data structures
@ -492,6 +508,7 @@ else if (abortval < 0) { /* mm or rsrv or int */
else R[rrn] = R[rrn] + rlnt; else R[rrn] = R[rrn] + rlnt;
} }
} }
PSL = PSL & ~PSL_TP; /* clear <tp> */
recqptr = 0; /* clear queue */ recqptr = 0; /* clear queue */
delta = PC - fault_PC; /* save delta PC */ delta = PC - fault_PC; /* save delta PC */
SETPC (fault_PC); /* restore PC */ SETPC (fault_PC); /* restore PC */
@ -681,27 +698,33 @@ for ( ;; ) {
case SH3|RB: case SH3|RW: case SH3|RL: case SH3|RB: case SH3|RW: case SH3|RL:
opnd[j++] = spec; opnd[j++] = spec;
break; break;
case SH0|RQ: case SH1|RQ: case SH2|RQ: case SH3|RQ: case SH0|RQ: case SH1|RQ: case SH2|RQ: case SH3|RQ:
opnd[j++] = spec; opnd[j++] = spec;
opnd[j++] = 0; opnd[j++] = 0;
break; break;
case SH0|RO: case SH1|RO: case SH2|RO: case SH3|RO: case SH0|RO: case SH1|RO: case SH2|RO: case SH3|RO:
opnd[j++] = spec; opnd[j++] = spec;
opnd[j++] = 0; opnd[j++] = 0;
opnd[j++] = 0; opnd[j++] = 0;
opnd[j++] = 0; opnd[j++] = 0;
break; break;
case SH0|RF: case SH1|RF: case SH2|RF: case SH3|RF: case SH0|RF: case SH1|RF: case SH2|RF: case SH3|RF:
opnd[j++] = (spec << 4) | 0x4000; opnd[j++] = (spec << 4) | 0x4000;
break; break;
case SH0|RD: case SH1|RD: case SH2|RD: case SH3|RD: case SH0|RD: case SH1|RD: case SH2|RD: case SH3|RD:
opnd[j++] = (spec << 4) | 0x4000; opnd[j++] = (spec << 4) | 0x4000;
opnd[j++] = 0; opnd[j++] = 0;
break; break;
case SH0|RG: case SH1|RG: case SH2|RG: case SH3|RG: case SH0|RG: case SH1|RG: case SH2|RG: case SH3|RG:
opnd[j++] = (spec << 1) | 0x4000; opnd[j++] = (spec << 1) | 0x4000;
opnd[j++] = 0; opnd[j++] = 0;
break; break;
case SH0|RH: case SH1|RH: case SH2|RH: case SH3|RH: case SH0|RH: case SH1|RH: case SH2|RH: case SH3|RH:
opnd[j++] = ((spec & 0x7) << 29) | (0x4000 | ((spec >> 3) & 0x7)); opnd[j++] = ((spec & 0x7) << 29) | (0x4000 | ((spec >> 3) & 0x7));
opnd[j++] = 0; opnd[j++] = 0;
@ -715,10 +738,12 @@ for ( ;; ) {
CHECK_FOR_PC; CHECK_FOR_PC;
opnd[j++] = R[rn] & BMASK; opnd[j++] = R[rn] & BMASK;
break; break;
case GRN|RW: case GRN|MW: case GRN|RW: case GRN|MW:
CHECK_FOR_PC; CHECK_FOR_PC;
opnd[j++] = R[rn] & WMASK; opnd[j++] = R[rn] & WMASK;
break; break;
case GRN|VB: case GRN|VB:
vfldrp1 = R[(rn + 1) & RGMASK]; vfldrp1 = R[(rn + 1) & RGMASK];
case GRN|WB: case GRN|WW: case GRN|WL: case GRN|WQ: case GRN|WO: case GRN|WB: case GRN|WW: case GRN|WL: case GRN|WQ: case GRN|WO:
@ -727,11 +752,13 @@ for ( ;; ) {
CHECK_FOR_PC; CHECK_FOR_PC;
opnd[j++] = R[rn]; opnd[j++] = R[rn];
break; break;
case GRN|RQ: case GRN|RD: case GRN|RG: case GRN|MQ: case GRN|RQ: case GRN|RD: case GRN|RG: case GRN|MQ:
CHECK_FOR_SP; CHECK_FOR_SP;
opnd[j++] = R[rn]; opnd[j++] = R[rn];
opnd[j++] = R[rn + 1]; opnd[j++] = R[rn + 1];
break; break;
case GRN|RO: case GRN|RH: case GRN|MO: case GRN|RO: case GRN|RH: case GRN|MO:
CHECK_FOR_AP; CHECK_FOR_AP;
opnd[j++] = R[rn]; opnd[j++] = R[rn];
@ -749,6 +776,7 @@ for ( ;; ) {
CHECK_FOR_PC; CHECK_FOR_PC;
va = opnd[j++] = R[rn]; va = opnd[j++] = R[rn];
break; break;
case ADC|VB: case ADC|VB:
case ADC|WB: case ADC|WW: case ADC|WL: case ADC|WQ: case ADC|WO: case ADC|WB: case ADC|WW: case ADC|WL: case ADC|WQ: case ADC|WO:
opnd[j++] = OP_MEM; opnd[j++] = OP_MEM;
@ -757,29 +785,55 @@ for ( ;; ) {
va = opnd[j++] = R[rn] = R[rn] - DR_LNT (disp); va = opnd[j++] = R[rn] = R[rn] - DR_LNT (disp);
recq[recqptr++] = RQ_REC (disp, rn); recq[recqptr++] = RQ_REC (disp, rn);
break; break;
case ADC|RB: case ADC|RW: case ADC|RL: case ADC|RF: case ADC|RB: case ADC|RW: case ADC|RL: case ADC|RF:
case ADC|MB: case ADC|MW: case ADC|ML:
R[rn] = R[rn] - (DR_LNT (disp)); R[rn] = R[rn] - (DR_LNT (disp));
recq[recqptr++] = RQ_REC (disp, rn); recq[recqptr++] = RQ_REC (disp, rn);
case RGD|RB: case RGD|RW: case RGD|RL: case RGD|RF: case RGD|RB: case RGD|RW: case RGD|RL: case RGD|RF:
case RGD|MB: case RGD|MW: case RGD|ML:
CHECK_FOR_PC; CHECK_FOR_PC;
opnd[j++] = Read (va = R[rn], DR_LNT (disp), RA); opnd[j++] = Read (va = R[rn], DR_LNT (disp), RA);
break; break;
case ADC|RQ: case ADC|RD: case ADC|RG: case ADC|MQ:
case ADC|RQ: case ADC|RD: case ADC|RG:
R[rn] = R[rn] - 8; R[rn] = R[rn] - 8;
recq[recqptr++] = RQ_REC (disp, rn); recq[recqptr++] = RQ_REC (disp, rn);
case RGD|RQ: case RGD|RD: case RGD|RG: case RGD|MQ: case RGD|RQ: case RGD|RD: case RGD|RG:
CHECK_FOR_PC; CHECK_FOR_PC;
opnd[j++] = Read (va = R[rn], L_LONG, RA); opnd[j++] = Read (va = R[rn], L_LONG, RA);
opnd[j++] = Read (R[rn] + 4, L_LONG, RA); opnd[j++] = Read (R[rn] + 4, L_LONG, RA);
break; break;
case ADC|RO: case ADC|RH: case ADC|MO:
case ADC|RO: case ADC|RH:
R[rn] = R[rn] - 16; R[rn] = R[rn] - 16;
recq[recqptr++] = RQ_REC (disp, rn); recq[recqptr++] = RQ_REC (disp, rn);
case RGD|RO: case RGD|RH: case RGD|MO: case RGD|RO: case RGD|RH:
CHECK_FOR_PC; CHECK_FOR_PC;
j = ReadOcta (va = R[rn], opnd, j, acc); j = ReadOcta (va = R[rn], opnd, j, RA);
break;
case ADC|MB: case ADC|MW: case ADC|ML:
R[rn] = R[rn] - (DR_LNT (disp));
recq[recqptr++] = RQ_REC (disp, rn);
case RGD|MB: case RGD|MW: case RGD|ML:
CHECK_FOR_PC;
opnd[j++] = Read (va = R[rn], DR_LNT (disp), WA);
break;
case ADC|MQ:
R[rn] = R[rn] - 8;
recq[recqptr++] = RQ_REC (disp, rn);
case RGD|MQ:
CHECK_FOR_PC;
opnd[j++] = Read (va = R[rn], L_LONG, WA);
opnd[j++] = Read (R[rn] + 4, L_LONG, WA);
break;
case ADC|MO:
R[rn] = R[rn] - 16;
recq[recqptr++] = RQ_REC (disp, rn);
case RGD|MO:
CHECK_FOR_PC;
j = ReadOcta (va = R[rn], opnd, j, WA);
break; break;
/* Autoincrement */ /* Autoincrement */
@ -806,8 +860,7 @@ for ( ;; ) {
recq[recqptr++] = RQ_REC (disp, rn); recq[recqptr++] = RQ_REC (disp, rn);
} }
break; break;
case AIN|MB: case AIN|MW: case AIN|ML:
/* CHECK_FOR_PC; */
case AIN|RB: case AIN|RW: case AIN|RL: case AIN|RF: case AIN|RB: case AIN|RW: case AIN|RL: case AIN|RF:
va = R[rn]; va = R[rn];
if (rn == nPC) { if (rn == nPC) {
@ -819,8 +872,7 @@ for ( ;; ) {
recq[recqptr++] = RQ_REC (disp, rn); recq[recqptr++] = RQ_REC (disp, rn);
} }
break; break;
case AIN|MQ:
/* CHECK_FOR_PC; */
case AIN|RQ: case AIN|RD: case AIN|RG: case AIN|RQ: case AIN|RD: case AIN|RG:
va = R[rn]; va = R[rn];
if (rn == nPC) { if (rn == nPC) {
@ -834,8 +886,7 @@ for ( ;; ) {
recq[recqptr++] = RQ_REC (disp, rn); recq[recqptr++] = RQ_REC (disp, rn);
} }
break; break;
case AIN|MO:
/* CHECK_FOR_PC; */
case AIN|RO: case AIN|RH: case AIN|RO: case AIN|RH:
va = R[rn]; va = R[rn];
if (rn == nPC) { if (rn == nPC) {
@ -845,7 +896,48 @@ for ( ;; ) {
GET_ISTR (opnd[j++], L_LONG); GET_ISTR (opnd[j++], L_LONG);
} }
else { else {
j = ReadOcta (va, opnd, j, acc); j = ReadOcta (va, opnd, j, RA);
R[rn] = R[rn] + 16;
recq[recqptr++] = RQ_REC (disp, rn);
}
break;
case AIN|MB: case AIN|MW: case AIN|ML:
va = R[rn];
if (rn == nPC) {
GET_ISTR (opnd[j++], DR_LNT (disp));
}
else {
opnd[j++] = Read (R[rn], DR_LNT (disp), WA);
R[rn] = R[rn] + DR_LNT (disp);
recq[recqptr++] = RQ_REC (disp, rn);
}
break;
case AIN|MQ:
va = R[rn];
if (rn == nPC) {
GET_ISTR (opnd[j++], L_LONG);
GET_ISTR (opnd[j++], L_LONG);
}
else {
opnd[j++] = Read (va, L_LONG, WA);
opnd[j++] = Read (va + 4, L_LONG, WA);
R[rn] = R[rn] + 8;
recq[recqptr++] = RQ_REC (disp, rn);
}
break;
case AIN|MO:
va = R[rn];
if (rn == nPC) {
GET_ISTR (opnd[j++], L_LONG);
GET_ISTR (opnd[j++], L_LONG);
GET_ISTR (opnd[j++], L_LONG);
GET_ISTR (opnd[j++], L_LONG);
}
else {
j = ReadOcta (va, opnd, j, WA);
R[rn] = R[rn] + 16; R[rn] = R[rn] + 16;
recq[recqptr++] = RQ_REC (disp, rn); recq[recqptr++] = RQ_REC (disp, rn);
} }
@ -864,8 +956,8 @@ for ( ;; ) {
recq[recqptr++] = RQ_REC (AID|RL, rn); recq[recqptr++] = RQ_REC (AID|RL, rn);
} }
break; break;
case AID|RB: case AID|RW: case AID|RL: case AID|RF: case AID|RB: case AID|RW: case AID|RL: case AID|RF:
case AID|MB: case AID|MW: case AID|ML:
if (rn == nPC) { if (rn == nPC) {
GET_ISTR (va, L_LONG); GET_ISTR (va, L_LONG);
} }
@ -876,7 +968,8 @@ for ( ;; ) {
} }
opnd[j++] = Read (va, DR_LNT (disp), RA); opnd[j++] = Read (va, DR_LNT (disp), RA);
break; break;
case AID|RQ: case AID|RD: case AID|RG: case AID|MQ:
case AID|RQ: case AID|RD: case AID|RG:
if (rn == nPC) { if (rn == nPC) {
GET_ISTR (va, L_LONG); GET_ISTR (va, L_LONG);
} }
@ -888,7 +981,8 @@ for ( ;; ) {
opnd[j++] = Read (va, L_LONG, RA); opnd[j++] = Read (va, L_LONG, RA);
opnd[j++] = Read (va + 4, L_LONG, RA); opnd[j++] = Read (va + 4, L_LONG, RA);
break; break;
case AID|RO: case AID|RH: case AID|MO:
case AID|RO: case AID|RH:
if (rn == nPC) { if (rn == nPC) {
GET_ISTR (va, L_LONG); GET_ISTR (va, L_LONG);
} }
@ -897,7 +991,44 @@ for ( ;; ) {
R[rn] = R[rn] + 4; R[rn] = R[rn] + 4;
recq[recqptr++] = RQ_REC (AID|RL, rn); recq[recqptr++] = RQ_REC (AID|RL, rn);
} }
j = ReadOcta (va, opnd, j, acc); j = ReadOcta (va, opnd, j, RA);
break;
case AID|MB: case AID|MW: case AID|ML:
if (rn == nPC) {
GET_ISTR (va, L_LONG);
}
else {
va = Read (R[rn], L_LONG, RA);
R[rn] = R[rn] + 4;
recq[recqptr++] = RQ_REC (AID|RL, rn);
}
opnd[j++] = Read (va, DR_LNT (disp), WA);
break;
case AID|MQ:
if (rn == nPC) {
GET_ISTR (va, L_LONG);
}
else {
va = Read (R[rn], L_LONG, RA);
R[rn] = R[rn] + 4;
recq[recqptr++] = RQ_REC (AID|RL, rn);
}
opnd[j++] = Read (va, L_LONG, WA);
opnd[j++] = Read (va + 4, L_LONG, WA);
break;
case AID|MO:
if (rn == nPC) {
GET_ISTR (va, L_LONG);
}
else {
va = Read (R[rn], L_LONG, RA);
R[rn] = R[rn] + 4;
recq[recqptr++] = RQ_REC (AID|RL, rn);
}
j = ReadOcta (va, opnd, j, WA);
break; break;
/* Byte displacement */ /* Byte displacement */
@ -909,22 +1040,43 @@ for ( ;; ) {
GET_ISTR (temp, L_BYTE); GET_ISTR (temp, L_BYTE);
va = opnd[j++] = R[rn] + SXTB (temp); va = opnd[j++] = R[rn] + SXTB (temp);
break; break;
case BDP|RB: case BDP|RW: case BDP|RL: case BDP|RF: case BDP|RB: case BDP|RW: case BDP|RL: case BDP|RF:
case BDP|MB: case BDP|MW: case BDP|ML:
GET_ISTR (temp, L_BYTE); GET_ISTR (temp, L_BYTE);
va = R[rn] + SXTB (temp); va = R[rn] + SXTB (temp);
opnd[j++] = Read (va, DR_LNT (disp), RA); opnd[j++] = Read (va, DR_LNT (disp), RA);
break; break;
case BDP|RQ: case BDP|RD: case BDP|RG: case BDP|MQ:
case BDP|RQ: case BDP|RD: case BDP|RG:
GET_ISTR (temp, L_BYTE); GET_ISTR (temp, L_BYTE);
va = R[rn] + SXTB (temp); va = R[rn] + SXTB (temp);
opnd[j++] = Read (va, L_LONG, RA); opnd[j++] = Read (va, L_LONG, RA);
opnd[j++] = Read (va + 4, L_LONG, RA); opnd[j++] = Read (va + 4, L_LONG, RA);
break; break;
case BDP|RO: case BDP|RH: case BDP|MO:
case BDP|RO: case BDP|RH:
GET_ISTR (temp, L_BYTE); GET_ISTR (temp, L_BYTE);
va = R[rn] + SXTB (temp); va = R[rn] + SXTB (temp);
j = ReadOcta (va, opnd, j, acc); j = ReadOcta (va, opnd, j, RA);
break;
case BDP|MB: case BDP|MW: case BDP|ML:
GET_ISTR (temp, L_BYTE);
va = R[rn] + SXTB (temp);
opnd[j++] = Read (va, DR_LNT (disp), WA);
break;
case BDP|MQ:
GET_ISTR (temp, L_BYTE);
va = R[rn] + SXTB (temp);
opnd[j++] = Read (va, L_LONG, WA);
opnd[j++] = Read (va + 4, L_LONG, WA);
break;
case BDP|MO:
GET_ISTR (temp, L_BYTE);
va = R[rn] + SXTB (temp);
j = ReadOcta (va, opnd, j, WA);
break; break;
/* Byte displacement deferred */ /* Byte displacement deferred */
@ -937,25 +1089,49 @@ for ( ;; ) {
iad = R[rn] + SXTB (temp); iad = R[rn] + SXTB (temp);
va = opnd[j++] = Read (iad, L_LONG, RA); va = opnd[j++] = Read (iad, L_LONG, RA);
break; break;
case BDD|RB: case BDD|RW: case BDD|RL: case BDD|RF: case BDD|RB: case BDD|RW: case BDD|RL: case BDD|RF:
case BDD|MB: case BDD|MW: case BDD|ML:
GET_ISTR (temp, L_BYTE); GET_ISTR (temp, L_BYTE);
iad = R[rn] + SXTB (temp); iad = R[rn] + SXTB (temp);
va = Read (iad, L_LONG, RA); va = Read (iad, L_LONG, RA);
opnd[j++] = Read (va, DR_LNT (disp), RA); opnd[j++] = Read (va, DR_LNT (disp), RA);
break; break;
case BDD|RQ: case BDD|RD: case BDD|RG: case BDD|MQ:
case BDD|RQ: case BDD|RD: case BDD|RG:
GET_ISTR (temp, L_BYTE); GET_ISTR (temp, L_BYTE);
iad = R[rn] + SXTB (temp); iad = R[rn] + SXTB (temp);
va = Read (iad, L_LONG, RA); va = Read (iad, L_LONG, RA);
opnd[j++] = Read (va, L_LONG, RA); opnd[j++] = Read (va, L_LONG, RA);
opnd[j++] = Read (va + 4, L_LONG, RA); opnd[j++] = Read (va + 4, L_LONG, RA);
break; break;
case BDD|RO: case BDD|RH: case BDD|MO:
case BDD|RO: case BDD|RH:
GET_ISTR (temp, L_BYTE); GET_ISTR (temp, L_BYTE);
iad = R[rn] + SXTB (temp); iad = R[rn] + SXTB (temp);
va = Read (iad, L_LONG, RA); va = Read (iad, L_LONG, RA);
j = ReadOcta (va, opnd, j, acc); j = ReadOcta (va, opnd, j, RA);
break;
case BDD|MB: case BDD|MW: case BDD|ML:
GET_ISTR (temp, L_BYTE);
iad = R[rn] + SXTB (temp);
va = Read (iad, L_LONG, RA);
opnd[j++] = Read (va, DR_LNT (disp), WA);
break;
case BDD|MQ:
GET_ISTR (temp, L_BYTE);
iad = R[rn] + SXTB (temp);
va = Read (iad, L_LONG, RA);
opnd[j++] = Read (va, L_LONG, WA);
opnd[j++] = Read (va + 4, L_LONG, WA);
break;
case BDD|MO:
GET_ISTR (temp, L_BYTE);
iad = R[rn] + SXTB (temp);
va = Read (iad, L_LONG, RA);
j = ReadOcta (va, opnd, j, WA);
break; break;
/* Word displacement */ /* Word displacement */
@ -967,22 +1143,43 @@ for ( ;; ) {
GET_ISTR (temp, L_WORD); GET_ISTR (temp, L_WORD);
va = opnd[j++] = R[rn] + SXTW (temp); va = opnd[j++] = R[rn] + SXTW (temp);
break; break;
case WDP|MB: case WDP|MW: case WDP|ML:
case WDP|RB: case WDP|RW: case WDP|RL: case WDP|RF: case WDP|RB: case WDP|RW: case WDP|RL: case WDP|RF:
GET_ISTR (temp, L_WORD); GET_ISTR (temp, L_WORD);
va = R[rn] + SXTW (temp); va = R[rn] + SXTW (temp);
opnd[j++] = Read (va, DR_LNT (disp), RA); opnd[j++] = Read (va, DR_LNT (disp), RA);
break; break;
case WDP|MQ: case WDP|RQ: case WDP|RD: case WDP|RG:
case WDP|RQ: case WDP|RD: case WDP|RG:
GET_ISTR (temp, L_WORD); GET_ISTR (temp, L_WORD);
va = R[rn] + SXTW (temp); va = R[rn] + SXTW (temp);
opnd[j++] = Read (va, L_LONG, RA); opnd[j++] = Read (va, L_LONG, RA);
opnd[j++] = Read (va + 4, L_LONG, RA); opnd[j++] = Read (va + 4, L_LONG, RA);
break; break;
case WDP|MO: case WDP|RO: case WDP|RH:
case WDP|RO: case WDP|RH:
GET_ISTR (temp, L_WORD); GET_ISTR (temp, L_WORD);
va = R[rn] + SXTW (temp); va = R[rn] + SXTW (temp);
j = ReadOcta (va, opnd, j, acc); j = ReadOcta (va, opnd, j, RA);
break;
case WDP|MB: case WDP|MW: case WDP|ML:
GET_ISTR (temp, L_WORD);
va = R[rn] + SXTW (temp);
opnd[j++] = Read (va, DR_LNT (disp), WA);
break;
case WDP|MQ:
GET_ISTR (temp, L_WORD);
va = R[rn] + SXTW (temp);
opnd[j++] = Read (va, L_LONG, WA);
opnd[j++] = Read (va + 4, L_LONG, WA);
break;
case WDP|MO:
GET_ISTR (temp, L_WORD);
va = R[rn] + SXTW (temp);
j = ReadOcta (va, opnd, j, WA);
break; break;
/* Word displacement deferred */ /* Word displacement deferred */
@ -995,25 +1192,49 @@ for ( ;; ) {
iad = R[rn] + SXTW (temp); iad = R[rn] + SXTW (temp);
va = opnd[j++] = Read (iad, L_LONG, RA); va = opnd[j++] = Read (iad, L_LONG, RA);
break; break;
case WDD|MB: case WDD|MW: case WDD|ML:
case WDD|RB: case WDD|RW: case WDD|RL: case WDD|RF: case WDD|RB: case WDD|RW: case WDD|RL: case WDD|RF:
GET_ISTR (temp, L_WORD); GET_ISTR (temp, L_WORD);
iad = R[rn] + SXTW (temp); iad = R[rn] + SXTW (temp);
va = Read (iad, L_LONG, RA); va = Read (iad, L_LONG, RA);
opnd[j++] = Read (va, DR_LNT (disp), RA); opnd[j++] = Read (va, DR_LNT (disp), RA);
break; break;
case WDD|MQ: case WDD|RQ: case WDD|RD: case WDD|RG:
case WDD|RQ: case WDD|RD: case WDD|RG:
GET_ISTR (temp, L_WORD); GET_ISTR (temp, L_WORD);
iad = R[rn] + SXTW (temp); iad = R[rn] + SXTW (temp);
va = Read (iad, L_LONG, RA); va = Read (iad, L_LONG, RA);
opnd[j++] = Read (va, L_LONG, RA); opnd[j++] = Read (va, L_LONG, RA);
opnd[j++] = Read (va + 4, L_LONG, RA); opnd[j++] = Read (va + 4, L_LONG, RA);
break; break;
case WDD|MO: case WDD|RO: case WDD|RH:
case WDD|RO: case WDD|RH:
GET_ISTR (temp, L_WORD); GET_ISTR (temp, L_WORD);
iad = R[rn] + SXTW (temp); iad = R[rn] + SXTW (temp);
va = Read (iad, L_LONG, RA); va = Read (iad, L_LONG, RA);
j = ReadOcta (va, opnd, j, acc); j = ReadOcta (va, opnd, j, RA);
break;
case WDD|MB: case WDD|MW: case WDD|ML:
GET_ISTR (temp, L_WORD);
iad = R[rn] + SXTW (temp);
va = Read (iad, L_LONG, RA);
opnd[j++] = Read (va, DR_LNT (disp), WA);
break;
case WDD|MQ:
GET_ISTR (temp, L_WORD);
iad = R[rn] + SXTW (temp);
va = Read (iad, L_LONG, RA);
opnd[j++] = Read (va, L_LONG, WA);
opnd[j++] = Read (va + 4, L_LONG, WA);
break;
case WDD|MO:
GET_ISTR (temp, L_WORD);
iad = R[rn] + SXTW (temp);
va = Read (iad, L_LONG, RA);
j = ReadOcta (va, opnd, j, WA);
break; break;
/* Longword displacement */ /* Longword displacement */
@ -1025,22 +1246,43 @@ for ( ;; ) {
GET_ISTR (temp, L_LONG); GET_ISTR (temp, L_LONG);
va = opnd[j++] = R[rn] + temp; va = opnd[j++] = R[rn] + temp;
break; break;
case LDP|MB: case LDP|MW: case LDP|ML:
case LDP|RB: case LDP|RW: case LDP|RL: case LDP|RF: case LDP|RB: case LDP|RW: case LDP|RL: case LDP|RF:
GET_ISTR (temp, L_LONG); GET_ISTR (temp, L_LONG);
va = R[rn] + temp; va = R[rn] + temp;
opnd[j++] = Read (va, DR_LNT (disp), RA); opnd[j++] = Read (va, DR_LNT (disp), RA);
break; break;
case LDP|MQ: case LDP|RQ: case LDP|RD: case LDP|RG:
case LDP|RQ: case LDP|RD: case LDP|RG:
GET_ISTR (temp, L_LONG); GET_ISTR (temp, L_LONG);
va = R[rn] + temp; va = R[rn] + temp;
opnd[j++] = Read (va, L_LONG, RA); opnd[j++] = Read (va, L_LONG, RA);
opnd[j++] = Read (va + 4, L_LONG, RA); opnd[j++] = Read (va + 4, L_LONG, RA);
break; break;
case LDP|MO: case LDP|RO: case LDP|RH:
case LDP|RO: case LDP|RH:
GET_ISTR (temp, L_LONG); GET_ISTR (temp, L_LONG);
va = R[rn] + temp; va = R[rn] + temp;
j = ReadOcta (va, opnd, j, acc); j = ReadOcta (va, opnd, j, RA);
break;
case LDP|MB: case LDP|MW: case LDP|ML:
GET_ISTR (temp, L_LONG);
va = R[rn] + temp;
opnd[j++] = Read (va, DR_LNT (disp), WA);
break;
case LDP|MQ:
GET_ISTR (temp, L_LONG);
va = R[rn] + temp;
opnd[j++] = Read (va, L_LONG, WA);
opnd[j++] = Read (va + 4, L_LONG, WA);
break;
case LDP|MO:
GET_ISTR (temp, L_LONG);
va = R[rn] + temp;
j = ReadOcta (va, opnd, j, WA);
break; break;
/* Longword displacement deferred */ /* Longword displacement deferred */
@ -1053,25 +1295,49 @@ for ( ;; ) {
iad = R[rn] + temp; iad = R[rn] + temp;
va = opnd[j++] = Read (iad, L_LONG, RA); va = opnd[j++] = Read (iad, L_LONG, RA);
break; break;
case LDD|MB: case LDD|MW: case LDD|ML:
case LDD|RB: case LDD|RW: case LDD|RL: case LDD|RF: case LDD|RB: case LDD|RW: case LDD|RL: case LDD|RF:
GET_ISTR (temp, L_LONG); GET_ISTR (temp, L_LONG);
iad = R[rn] + temp; iad = R[rn] + temp;
va = Read (iad, L_LONG, RA); va = Read (iad, L_LONG, RA);
opnd[j++] = Read (va, DR_LNT (disp), RA); opnd[j++] = Read (va, DR_LNT (disp), RA);
break; break;
case LDD|MQ: case LDD|RQ: case LDD|RD: case LDD|RG:
case LDD|RQ: case LDD|RD: case LDD|RG:
GET_ISTR (temp, L_LONG); GET_ISTR (temp, L_LONG);
iad = R[rn] + temp; iad = R[rn] + temp;
va = Read (iad, L_LONG, RA); va = Read (iad, L_LONG, RA);
opnd[j++] = Read (va, L_LONG, RA); opnd[j++] = Read (va, L_LONG, RA);
opnd[j++] = Read (va + 4, L_LONG, RA); opnd[j++] = Read (va + 4, L_LONG, RA);
break; break;
case LDD|MO: case LDD|RO: case LDD|RH:
case LDD|RO: case LDD|RH:
GET_ISTR (temp, L_LONG); GET_ISTR (temp, L_LONG);
iad = R[rn] + temp; iad = R[rn] + temp;
va = Read (iad, L_LONG, RA); va = Read (iad, L_LONG, RA);
j = ReadOcta (va, opnd, j, acc); j = ReadOcta (va, opnd, j, RA);
break;
case LDD|MB: case LDD|MW: case LDD|ML:
GET_ISTR (temp, L_LONG);
iad = R[rn] + temp;
va = Read (iad, L_LONG, RA);
opnd[j++] = Read (va, DR_LNT (disp), WA);
break;
case LDD|MQ:
GET_ISTR (temp, L_LONG);
iad = R[rn] + temp;
va = Read (iad, L_LONG, RA);
opnd[j++] = Read (va, L_LONG, WA);
opnd[j++] = Read (va + 4, L_LONG, WA);
break;
case LDD|MO:
GET_ISTR (temp, L_LONG);
iad = R[rn] + temp;
va = Read (iad, L_LONG, RA);
j = ReadOcta (va, opnd, j, WA);
break; break;
/* Index */ /* Index */
@ -1094,12 +1360,14 @@ for ( ;; ) {
CHECK_FOR_PC; CHECK_FOR_PC;
index = index + R[rn]; index = index + R[rn];
break; break;
case AIN: case AIN:
CHECK_FOR_PC; CHECK_FOR_PC;
index = index + R[rn]; index = index + R[rn];
R[rn] = R[rn] + DR_LNT (disp); R[rn] = R[rn] + DR_LNT (disp);
recq[recqptr++] = RQ_REC (AIN | (disp & DR_LNMASK), rn); recq[recqptr++] = RQ_REC (AIN | (disp & DR_LNMASK), rn);
break; break;
case AID: case AID:
if (rn == nPC) { if (rn == nPC) {
GET_ISTR (temp, L_LONG); GET_ISTR (temp, L_LONG);
@ -1111,30 +1379,37 @@ for ( ;; ) {
} }
index = temp + index; index = temp + index;
break; break;
case BDP: case BDP:
GET_ISTR (temp, L_BYTE); GET_ISTR (temp, L_BYTE);
index = index + R[rn] + SXTB (temp); index = index + R[rn] + SXTB (temp);
break; break;
case BDD: case BDD:
GET_ISTR (temp, L_BYTE); GET_ISTR (temp, L_BYTE);
index = index + Read (R[rn] + SXTB (temp), L_LONG, RA); index = index + Read (R[rn] + SXTB (temp), L_LONG, RA);
break; break;
case WDP: case WDP:
GET_ISTR (temp, L_WORD); GET_ISTR (temp, L_WORD);
index = index + R[rn] + SXTW (temp); index = index + R[rn] + SXTW (temp);
break; break;
case WDD: case WDD:
GET_ISTR (temp, L_WORD); GET_ISTR (temp, L_WORD);
index = index + Read (R[rn] + SXTW (temp), L_LONG, RA); index = index + Read (R[rn] + SXTW (temp), L_LONG, RA);
break; break;
case LDP: case LDP:
GET_ISTR (temp, L_LONG); GET_ISTR (temp, L_LONG);
index = index + R[rn] + temp; index = index + R[rn] + temp;
break; break;
case LDD: case LDD:
GET_ISTR (temp, L_LONG); GET_ISTR (temp, L_LONG);
index = index + Read (R[rn] + temp, L_LONG, RA); index = index + Read (R[rn] + temp, L_LONG, RA);
break; break;
default: default:
RSVD_ADDR_FAULT; /* end case idxspec */ RSVD_ADDR_FAULT; /* end case idxspec */
} }
@ -1145,16 +1420,31 @@ for ( ;; ) {
case AB: case AW: case AL: case AQ: case AO: case AB: case AW: case AL: case AQ: case AO:
va = opnd[j++] = index; va = opnd[j++] = index;
break; break;
case MB: case MW: case ML:
case RB: case RW: case RL: case RB: case RW: case RL:
opnd[j++] = Read (va = index, DR_LNT (disp), RA); opnd[j++] = Read (va = index, DR_LNT (disp), RA);
break; break;
case RQ: case MQ:
case RQ:
opnd[j++] = Read (va = index, L_LONG, RA); opnd[j++] = Read (va = index, L_LONG, RA);
opnd[j++] = Read (index + 4, L_LONG, RA); opnd[j++] = Read (index + 4, L_LONG, RA);
break; break;
case RO: case MO:
j = ReadOcta (va = index, opnd, j, acc); case RO:
j = ReadOcta (va = index, opnd, j, RA);
break;
case MB: case MW: case ML:
opnd[j++] = Read (va = index, DR_LNT (disp), WA);
break;
case MQ:
opnd[j++] = Read (va = index, L_LONG, WA);
opnd[j++] = Read (index + 4, L_LONG, WA);
break;
case MO:
j = ReadOcta (va = index, opnd, j, WA);
break; break;
} /* end case access/lnt */ } /* end case access/lnt */
break; /* end index */ break; /* end index */
@ -1169,12 +1459,24 @@ for ( ;; ) {
/* Optionally record instruction history */ /* Optionally record instruction history */
if (hst_lnt) { if (hst_lnt) {
int32 lim;
t_value wd;
hst[hst_p].iPC = fault_PC; hst[hst_p].iPC = fault_PC;
hst[hst_p].PSL = PSL | cc; hst[hst_p].PSL = PSL | cc;
hst[hst_p].opc = opc; hst[hst_p].opc = opc;
hst[hst_p].brdest = brdisp + PC; for (i = 0; i < j; i++)
for (i = 0; i < OPND_SIZE; i++)
hst[hst_p].opnd[i] = opnd[i]; hst[hst_p].opnd[i] = opnd[i];
lim = PC - fault_PC;
if ((uint32) lim > INST_SIZE) lim = INST_SIZE;
for (i = 0; i < lim; i++) {
if ((cpu_ex (&wd, fault_PC + i, &cpu_unit, SWMASK ('V'))) == SCPE_OK)
hst[hst_p].inst[i] = (uint8) wd;
else {
hst[hst_p].inst[0] = hst[hst_p].inst[1] = 0xFF;
break;
}
}
hst_p = hst_p + 1; hst_p = hst_p + 1;
if (hst_p >= hst_lnt) hst_p = 0; if (hst_p >= hst_lnt) hst_p = 0;
} }
@ -1384,16 +1686,13 @@ for ( ;; ) {
break; break;
case ADAWI: case ADAWI:
if (op1 >= 0) { /* reg? ADDW2 */ if (op1 >= 0) temp = R[op1] & WMASK; /* reg? ADDW2 */
temp = R[op1];
r = R[op1] = (op0 + temp) & WMASK;
}
else { else {
if (op2 & 1) RSVD_OPND_FAULT; /* mem? chk align */ if (op2 & 1) RSVD_OPND_FAULT; /* mem? chk align */
temp = Read (op2, L_WORD, WA); /* ok, ADDW2 */ temp = Read (op2, L_WORD, WA); /* ok, ADDW2 */
r = (op0 + temp) & WMASK;
WRITE_W (r);
} }
r = (op0 + temp) & WMASK;
WRITE_W (r);
CC_ADD_W (r, op0, temp); /* set cc's */ CC_ADD_W (r, op0, temp); /* set cc's */
break; break;
@ -2415,7 +2714,7 @@ for ( ;; ) {
WRITE_L (r); /* write result */ WRITE_L (r); /* write result */
CC_IIZP_FP (r); /* set cc's */ CC_IIZP_FP (r); /* set cc's */
if ((temp & CC_Z) || ((op1 & FPSIGN)? /* test br cond */ if ((temp & CC_Z) || ((op1 & FPSIGN)? /* test br cond */
!(temp & CC_N): (temp & CC_N))) BRANCHW (brdisp); !(temp & CC_N): (temp & CC_N))) BRANCHW (brdisp);
break; break;
case ACBD: case ACBD:
@ -2423,8 +2722,8 @@ for ( ;; ) {
temp = op_cmpfd (r, rh, op0, op1); temp = op_cmpfd (r, rh, op0, op1);
WRITE_Q (r, rh); WRITE_Q (r, rh);
CC_IIZP_FP (r); CC_IIZP_FP (r);
if ((temp & CC_Z) || ((op1 & FPSIGN)? /* test br cond */ if ((temp & CC_Z) || ((op2 & FPSIGN)? /* test br cond */
!(temp & CC_N): (temp & CC_N))) BRANCHW (brdisp); !(temp & CC_N): (temp & CC_N))) BRANCHW (brdisp);
break; break;
case ACBG: case ACBG:
@ -2432,8 +2731,8 @@ for ( ;; ) {
temp = op_cmpg (r, rh, op0, op1); temp = op_cmpg (r, rh, op0, op1);
WRITE_Q (r, rh); WRITE_Q (r, rh);
CC_IIZP_FP (r); CC_IIZP_FP (r);
if ((temp & CC_Z) || ((op1 & FPSIGN)? /* test br cond */ if ((temp & CC_Z) || ((op2 & FPSIGN)? /* test br cond */
!(temp & CC_N): (temp & CC_N))) BRANCHW (brdisp); !(temp & CC_N): (temp & CC_N))) BRANCHW (brdisp);
break; break;
/* EMODF /* EMODF
@ -2637,10 +2936,10 @@ return val;
int32 ReadOcta (int32 va, int32 *opnd, int32 j, int32 acc) int32 ReadOcta (int32 va, int32 *opnd, int32 j, int32 acc)
{ {
opnd[j++] = Read (va, L_LONG, RA); opnd[j++] = Read (va, L_LONG, acc);
opnd[j++] = Read (va + 4, L_LONG, RA); opnd[j++] = Read (va + 4, L_LONG, acc);
opnd[j++] = Read (va + 8, L_LONG, RA); opnd[j++] = Read (va + 8, L_LONG, acc);
opnd[j++] = Read (va + 12, L_LONG, RA); opnd[j++] = Read (va + 12, L_LONG, acc);
return j; return j;
} }
@ -2672,7 +2971,10 @@ int32 st;
uint32 addr = (uint32) exta; uint32 addr = (uint32) exta;
if (vptr == NULL) return SCPE_ARG; if (vptr == NULL) return SCPE_ARG;
if (sw & SWMASK ('V')) addr = Test (addr, RD, &st); if (sw & SWMASK ('V')) {
int32 acc = cpu_get_vsw (sw);
addr = Test (addr, acc, &st);
}
else addr = addr & PAMASK; else addr = addr & PAMASK;
if (ADDR_IS_MEM (addr) || ADDR_IS_CDG (addr) || if (ADDR_IS_MEM (addr) || ADDR_IS_CDG (addr) ||
ADDR_IS_ROM (addr) || ADDR_IS_NVR (addr)) { ADDR_IS_ROM (addr) || ADDR_IS_NVR (addr)) {
@ -2689,7 +2991,10 @@ t_stat cpu_dep (t_value val, t_addr exta, UNIT *uptr, int32 sw)
int32 st; int32 st;
uint32 addr = (uint32) exta; uint32 addr = (uint32) exta;
if (sw & SWMASK ('V')) addr = Test (addr, RD, &st); if (sw & SWMASK ('V')) {
int32 acc = cpu_get_vsw (sw);
addr = Test (addr, acc, &st);
}
else addr = addr & PAMASK; else addr = addr & PAMASK;
if (ADDR_IS_MEM (addr) || ADDR_IS_CDG (addr) || if (ADDR_IS_MEM (addr) || ADDR_IS_CDG (addr) ||
ADDR_IS_NVR (addr)) { ADDR_IS_NVR (addr)) {
@ -2746,7 +3051,8 @@ static const char *mm_str[] = {
if (cptr) { if (cptr) {
va = (uint32) get_uint (cptr, 16, 0xFFFFFFFF, &r); va = (uint32) get_uint (cptr, 16, 0xFFFFFFFF, &r);
if (r == SCPE_OK) { if (r == SCPE_OK) {
pa = Test (va, RD, &st); int32 acc = cpu_get_vsw (sim_switches);
pa = Test (va, acc, &st);
if (st == PR_OK) fprintf (of, "Virtual %-X = physical %-X\n", va, pa); if (st == PR_OK) fprintf (of, "Virtual %-X = physical %-X\n", va, pa);
else fprintf (of, "Virtual %-X: %s\n", va, mm_str[st]); else fprintf (of, "Virtual %-X: %s\n", va, mm_str[st]);
return SCPE_OK; return SCPE_OK;
@ -2756,6 +3062,21 @@ fprintf (of, "Invalid argument\n");
return SCPE_OK; return SCPE_OK;
} }
/* Get access mode for examine, deposit, show virtual */
int32 cpu_get_vsw (int32 sw)
{
int32 md;
set_map_reg (); /* update dyn reg */
if (sw & SWMASK ('K')) md = KERN;
else if (sw & SWMASK ('E')) md = EXEC;
else if (sw & SWMASK ('S')) md = SUPV;
else if (sw & SWMASK ('U')) md = USER;
else md = PSL_GETCUR (PSL);
return ACC_MASK (md);
}
/* Set history */ /* Set history */
t_stat cpu_set_hist (UNIT *uptr, int32 val, char *cptr, void *desc) t_stat cpu_set_hist (UNIT *uptr, int32 val, char *cptr, void *desc)
@ -2788,11 +3109,14 @@ return SCPE_OK;
t_stat cpu_show_hist (FILE *st, UNIT *uptr, int32 val, void *desc) t_stat cpu_show_hist (FILE *st, UNIT *uptr, int32 val, void *desc)
{ {
int32 i, j, k, di, disp, numspec, lnt; int32 i, k, di, lnt, numspec;
char *cptr = (char *) desc; char *cptr = (char *) desc;
t_stat r; t_stat r;
InstHistory *h; InstHistory *h;
extern const char *opcode[]; extern const char *opcode[];
extern t_value *sim_eval;
extern t_stat fprint_sym (FILE *ofile, t_addr addr, t_value *val,
UNIT *uptr, int32 sw);
if (hst_lnt == 0) return SCPE_NOFNC; /* enabled? */ if (hst_lnt == 0) return SCPE_NOFNC; /* enabled? */
if (cptr) { if (cptr) {
@ -2806,43 +3130,70 @@ fprintf (st, "PC PSL IR\n\n");
for (k = 0; k < lnt; k++) { /* print specified */ for (k = 0; k < lnt; k++) { /* print specified */
h = &hst[(di++) % hst_lnt]; /* entry pointer */ h = &hst[(di++) % hst_lnt]; /* entry pointer */
if (h->iPC == 0) continue; /* filled in? */ if (h->iPC == 0) continue; /* filled in? */
fprintf(st, "%08X %08X ", h->iPC, h->PSL); /* PC, PSL */ fprintf(st, "%08X %08X| ", h->iPC, h->PSL); /* PC, PSL */
numspec = drom[h->opc][0] & DR_NSPMASK; /* #specifiers */ numspec = drom[h->opc][0] & DR_NSPMASK; /* #specifiers */
if (opcode[h->opc] == NULL) /* undefined? */ if (opcode[h->opc] == NULL) /* undefined? */
fprintf (st, "%03X (undefined)", h->opc); fprintf (st, "%03X (undefined)", h->opc);
else if (h->PSL & PSL_FPD) /* FPD set? */ else if (h->PSL & PSL_FPD) /* FPD set? */
fprintf (st, "%s FPD set", opcode[h->opc]); fprintf (st, "%s FPD set", opcode[h->opc]);
else { /* normal */ else { /* normal */
fprintf (st, "%s", opcode[h->opc]); /* print opcode */ for (i = 0; i < INST_SIZE; i++) sim_eval[i] = h->inst[i];
for (i = 1, j = 0; i <= numspec; i++) { /* loop thru specs */ if ((fprint_sym (st, h->iPC, sim_eval, &cpu_unit, SWMASK ('M'))) > 0)
fputc ((i == 1)? ' ': ',', st); /* separator */ fprintf (st, "%03X (undefined)", h->opc);
disp = drom[h->opc][i]; /* specifier type */ if ((numspec > 1) ||
if (disp == RG) disp = RQ; /* fix specials */ ((numspec == 1) && (drom[h->opc][1] < BB))) {
else if (disp >= BB) fprintf (st, "%X", h->brdest); if (cpu_show_opnd (st, h, 0)) { /* operands; more? */
else switch (disp & (DR_LNMASK|DR_ACMASK)) { if (cpu_show_opnd (st, h, 1)) { /* 2nd line; more? */
case RB: case RW: case RL: /* read */ cpu_show_opnd (st, h, 2); /* octa, 3rd/4th */
case AB: case AW: case AL: case AQ: case AO: /* address */ cpu_show_opnd (st, h, 3);
case MB: case MW: case ML: /* modify */ }
fprintf (st, "%X", h->opnd[j++]); }
break; }
case RQ: case MQ: /* read, modify quad */
fprintf (st, "%X%08X", h->opnd[j], h->opnd[j + 1]);
j = j + 2;
break;
case RO: case MO: /* read, modify octa */
fprintf (st, "%X%08X%08X%08X", h->opnd[j],
h->opnd[j + 1], h->opnd[j + 2], h->opnd[j + 3]);
j = j + 4;
break;
case WB: case WW: case WL: case WQ: case WO: /* write */
if (h->opnd[j] < 0) fprintf (st, "%X", h->opnd[j + 1]);
else fprintf (st, "R%d", h->opnd[j]);
j = j + 2;
break;
} /* end case */
} /* end for */
} /* end else */ } /* end else */
fputc ('\n', st); /* end line */ fputc ('\n', st); /* end line */
} /* end for */ } /* end for */
return SCPE_OK; return SCPE_OK;
} }
t_bool cpu_show_opnd (FILE *st, InstHistory *h, int32 line)
{
int32 numspec, i, j, disp;
t_bool more;
numspec = drom[h->opc][0] & DR_NSPMASK; /* #specifiers */
fputs ("\n ", st); /* space */
for (i = 1, j = 0, more = FALSE; i <= numspec; i++) { /* loop thru specs */
disp = drom[h->opc][i]; /* specifier type */
if (disp == RG) disp = RQ; /* fix specials */
else if (disp >= BB) break; /* ignore branches */
else switch (disp & (DR_LNMASK|DR_ACMASK)) {
case RB: case RW: case RL: /* read */
case AB: case AW: case AL: case AQ: case AO: /* address */
case MB: case MW: case ML: /* modify */
if (line == 0) fprintf (st, " %08X", h->opnd[j]);
else fputs (" ", st);
j = j + 1;
break;
case RQ: case MQ: /* read, modify quad */
if (line <= 1) fprintf (st, " %08X", h->opnd[j + line]);
else fputs (" ", st);
if (line == 0) more = TRUE;
j = j + 2;
break;
case RO: case MO: /* read, modify octa */
fprintf (st, " %08X", h->opnd[j + line]);
more = TRUE;
j = j + 4;
break;
case WB: case WW: case WL: case WQ: case WO: /* write */
if (line == 0) fprintf (st, " %08X", h->opnd[j + 1]);
else fputs (" ", st);
j = j + 2;
break;
} /* end case */
} /* end for */
return more;
}

View file

@ -1,6 +1,6 @@
/* vax_cpu1.c: VAX complex instructions /* vax_cpu1.c: VAX complex instructions
Copyright (c) 1998-2005, Robert M Supnik Copyright (c) 1998-2006, Robert M Supnik
Permission is hereby granted, free of charge, to any person obtaining a Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"), copy of this software and associated documentation files (the "Software"),
@ -23,7 +23,9 @@
used in advertising or otherwise to promote the sale, use or other dealings used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from Robert M Supnik. in this Software without prior written authorization from Robert M Supnik.
22-Sep-05 RMS Fixed declarations (from Sterling Garwood) 10-May-06 RMS Added access check on system PTE for 11/780
Added mbz check in LDPCTX for 11/780
22-Sep-06 RMS Fixed declarations (from Sterling Garwood)
30-Sep-04 RMS Added conditionals for full VAX 30-Sep-04 RMS Added conditionals for full VAX
Moved emulation to vax_cis.c Moved emulation to vax_cis.c
Moved model-specific IPRs to system module Moved model-specific IPRs to system module
@ -1200,7 +1202,7 @@ return newpsl & CC_MASK; /* set new cc */
void op_ldpctx (int32 acc) void op_ldpctx (int32 acc)
{ {
int32 newpc, newpsl, pcbpa; int32 newpc, newpsl, pcbpa, t;
if (PSL & PSL_CUR) RSVD_INST_FAULT; /* must be kernel */ if (PSL & PSL_CUR) RSVD_INST_FAULT; /* must be kernel */
pcbpa = PCBB & PAMASK; /* phys address */ pcbpa = PCBB & PAMASK; /* phys address */
@ -1224,16 +1226,26 @@ R[12] = ReadLP (pcbpa + 64);
R[13] = ReadLP (pcbpa + 68); R[13] = ReadLP (pcbpa + 68);
newpc = ReadLP (pcbpa + 72); /* get PC, PSL */ newpc = ReadLP (pcbpa + 72); /* get PC, PSL */
newpsl = ReadLP (pcbpa + 76); newpsl = ReadLP (pcbpa + 76);
P0BR = ReadLP (pcbpa + 80); /* restore mem mgt */
P0LR = ReadLP (pcbpa + 84); t = ReadLP (pcbpa + 80);
P1BR = ReadLP (pcbpa + 88); ML_BR_TEST (t); /* validate P0BR */
P1LR = ReadLP (pcbpa + 92); P0BR = t & BR_MASK; /* restore P0BR */
ASTLVL = (P0LR >> 24) & AST_MASK; /* restore AST */ t = ReadLP (pcbpa + 84);
pme = (P1LR >> 31) & 1; /* restore PME */ LP_MBZ84_TEST (t); /* test mbz */
P0BR = P0BR & BR_MASK; ML_LR_TEST (t & LR_MASK); /* validate P0LR */
P0LR = P0LR & LR_MASK; P0LR = t & LR_MASK; /* restore P0LR */
P1BR = P1BR & BR_MASK; t = (t >> 24) & AST_MASK;
P1LR = P1LR & LR_MASK; LP_AST_TEST (t); /* validate AST */
ASTLVL = t; /* restore AST */
t = ReadLP (pcbpa + 88);
ML_BR_TEST (t + 0x800000); /* validate P1BR */
P1BR = t & BR_MASK; /* restore P1BR */
t = ReadLP (pcbpa + 92);
LP_MBZ92_TEST (t); /* test MBZ */
ML_LR_TEST (t & LR_MASK); /* validate P1LR */
P1LR = t & LR_MASK; /* restore P1LR */
pme = (t >> 31) & 1; /* restore PME */
zap_tb (0); /* clear process TB */ zap_tb (0); /* clear process TB */
set_map_reg (); set_map_reg ();
if (DEBUG_PRI (cpu_dev, LOG_CPU_P)) fprintf (sim_deb, if (DEBUG_PRI (cpu_dev, LOG_CPU_P)) fprintf (sim_deb,
@ -1372,46 +1384,54 @@ switch (prn) { /* case on reg # */
break; break;
case MT_P0BR: /* P0BR */ case MT_P0BR: /* P0BR */
ML_BR_TEST (val); /* validate */
P0BR = val & BR_MASK; /* lw aligned */ P0BR = val & BR_MASK; /* lw aligned */
zap_tb (0); /* clr proc TLB */ zap_tb (0); /* clr proc TLB */
set_map_reg (); set_map_reg ();
break; break;
case MT_P0LR: /* P0LR */ case MT_P0LR: /* P0LR */
ML_LR_TEST (val & LR_MASK); /* validate */
P0LR = val & LR_MASK; P0LR = val & LR_MASK;
zap_tb (0); /* clr proc TLB */ zap_tb (0); /* clr proc TLB */
set_map_reg (); set_map_reg ();
break; break;
case MT_P1BR: /* P1BR */ case MT_P1BR: /* P1BR */
ML_BR_TEST (val + 0x800000); /* validate */
P1BR = val & BR_MASK; /* lw aligned */ P1BR = val & BR_MASK; /* lw aligned */
zap_tb (0); /* clr proc TLB */ zap_tb (0); /* clr proc TLB */
set_map_reg (); set_map_reg ();
break; break;
case MT_P1LR: /* P1LR */ case MT_P1LR: /* P1LR */
ML_LR_TEST (val & LR_MASK); /* validate */
P1LR = val & LR_MASK; P1LR = val & LR_MASK;
zap_tb (0); /* clr proc TLB */ zap_tb (0); /* clr proc TLB */
set_map_reg (); set_map_reg ();
break; break;
case MT_SBR: /* SBR */ case MT_SBR: /* SBR */
ML_PA_TEST (val); /* validate */
SBR = val & BR_MASK; /* lw aligned */ SBR = val & BR_MASK; /* lw aligned */
zap_tb (1); /* clr entire TLB */ zap_tb (1); /* clr entire TLB */
set_map_reg (); set_map_reg ();
break; break;
case MT_SLR: /* SLR */ case MT_SLR: /* SLR */
ML_LR_TEST (val & LR_MASK); /* validate */
SLR = val & LR_MASK; SLR = val & LR_MASK;
zap_tb (1); /* clr entire TLB */ zap_tb (1); /* clr entire TLB */
set_map_reg (); set_map_reg ();
break; break;
case MT_SCBB: /* SCBB */ case MT_SCBB: /* SCBB */
ML_PA_TEST (val); /* validate */
SCBB = val & BR_MASK; /* lw aligned */ SCBB = val & BR_MASK; /* lw aligned */
break; break;
case MT_PCBB: /* PCBB */ case MT_PCBB: /* PCBB */
ML_PA_TEST (val); /* validate */
PCBB = val & BR_MASK; /* lw aligned */ PCBB = val & BR_MASK; /* lw aligned */
break; break;

View file

@ -1,6 +1,6 @@
/* vax_defs.h: VAX architecture definitions file /* vax_defs.h: VAX architecture definitions file
Copyright (c) 1998-2005, Robert M Supnik Copyright (c) 1998-2006, Robert M Supnik
Permission is hereby granted, free of charge, to any person obtaining a Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"), copy of this software and associated documentation files (the "Software"),
@ -26,6 +26,8 @@
The author gratefully acknowledges the help of Stephen Shirron, Antonio The author gratefully acknowledges the help of Stephen Shirron, Antonio
Carlini, and Kevin Peterson in providing specifications for the Qbus VAX's Carlini, and Kevin Peterson in providing specifications for the Qbus VAX's
09-May-06 RMS Added system PTE ACV error code
03-May-06 RMS Added EDITPC get/put cc's macros
03-Nov-05 RMS Added 780 stop codes 03-Nov-05 RMS Added 780 stop codes
22-Jul-05 RMS Fixed warning from Solaris C (from Doug Gwyn) 22-Jul-05 RMS Fixed warning from Solaris C (from Doug Gwyn)
02-Sep-04 RMS Added octa specifier definitions 02-Sep-04 RMS Added octa specifier definitions
@ -235,6 +237,7 @@
#define PTE_V (1u << PTE_V_V) #define PTE_V (1u << PTE_V_V)
#define PTE_V_ACC 27 /* access */ #define PTE_V_ACC 27 /* access */
#define PTE_M_ACC 0xF #define PTE_M_ACC 0xF
#define PTE_ACC (PTE_M_ACC << PTE_V_ACC)
#define PTE_V_M 26 /* modified */ #define PTE_V_M 26 /* modified */
#define PTE_M (1u << PTE_V_M) #define PTE_M (1u << PTE_V_M)
#define PTE_GETACC(x) (((x) >> PTE_V_ACC) & PTE_M_ACC) #define PTE_GETACC(x) (((x) >> PTE_V_ACC) & PTE_M_ACC)
@ -310,14 +313,19 @@
/* EDITPC R2 packup parameters */ /* EDITPC R2 packup parameters */
#define ED_V_CC 16 /* condition codes */
#define ED_M_CC 0xFF
#define ED_CC (ED_M_CC << ED_V_CC)
#define ED_V_SIGN 8 /* sign */ #define ED_V_SIGN 8 /* sign */
#define ED_M_SIGN 0xFF #define ED_M_SIGN 0xFF
#define ED_SIGN (ED_M_SIGN << ED_V_SIGN) #define ED_SIGN (ED_M_SIGN << ED_V_SIGN)
#define ED_V_FILL 0 /* fill */ #define ED_V_FILL 0 /* fill */
#define ED_M_FILL 0xFF #define ED_M_FILL 0xFF
#define ED_FILL (ED_M_FILL << ED_V_FILL) #define ED_FILL (ED_M_FILL << ED_V_FILL)
#define ED_GETCC(x) (((x) >> ED_V_CC) & CC_MASK)
#define ED_GETSIGN(x) (((x) >> ED_V_SIGN) & ED_M_SIGN) #define ED_GETSIGN(x) (((x) >> ED_V_SIGN) & ED_M_SIGN)
#define ED_GETFILL(x) (((x) >> ED_V_FILL) & ED_M_FILL) #define ED_GETFILL(x) (((x) >> ED_V_FILL) & ED_M_FILL)
#define ED_PUTCC(r,x) (((r) & ~ED_CC) | (((x) << ED_V_CC) & ED_CC))
#define ED_PUTSIGN(r,x) (((r) & ~ED_SIGN) | (((x) << ED_V_SIGN) & ED_SIGN)) #define ED_PUTSIGN(r,x) (((r) & ~ED_SIGN) | (((x) << ED_V_SIGN) & ED_SIGN))
#define ED_PUTFILL(r,x) (((r) & ~ED_FILL) | (((x) << ED_V_FILL) & ED_FILL)) #define ED_PUTFILL(r,x) (((r) & ~ED_FILL) | (((x) << ED_V_FILL) & ED_FILL))
@ -461,7 +469,7 @@
#define PR_ACV 0 /* ACV */ #define PR_ACV 0 /* ACV */
#define PR_LNV 1 /* length viol */ #define PR_LNV 1 /* length viol */
/* #define PR_PACV 2 /* impossible */ #define PR_PACV 2 /* pte ACV (780) */
#define PR_PLNV 3 /* pte len viol */ #define PR_PLNV 3 /* pte len viol */
#define PR_TNV 4 /* TNV */ #define PR_TNV 4 /* TNV */
/* #define PR_TB 5 /* impossible */ /* #define PR_TB 5 /* impossible */

File diff suppressed because it is too large Load diff

View file

@ -1,6 +1,6 @@
/* vax_fpa.c - VAX f_, d_, g_floating instructions /* vax_fpa.c - VAX f_, d_, g_floating instructions
Copyright (c) 1998-2005, Robert M Supnik Copyright (c) 1998-2006, Robert M Supnik
Permission is hereby granted, free of charge, to any person obtaining a Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"), copy of this software and associated documentation files (the "Software"),
@ -23,6 +23,17 @@
used in advertising or otherwise to promote the sale, use or other dealings used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from Robert M Supnik. in this Software without prior written authorization from Robert M Supnik.
16-May-06 RMS Fixed bug in 32b floating multiply routine
Fixed bug in 64b extended modulus routine
03-May-06 RMS Fixed POLYD, POLYG to clear R4, R5
Fixed POLYD, POLYG to set R3 correctly
Fixed POLYD, POLYG to not exit prematurely if arg = 0
Fixed POLYD, POLYG to do full 64b multiply
Fixed POLYF, POLYD, POLYG to remove truncation on add
Fixed POLYF, POLYD, POLYG to mask mul reslt to 31b/63b/63b
Fixed fp add routine to test for zero via fraction
to support "denormal" argument from POLYF, POLYD, POLYG
(all reported by Tim Stark)
27-Sep-05 RMS Fixed bug in 32b structure definitions (from Jason Stevens) 27-Sep-05 RMS Fixed bug in 32b structure definitions (from Jason Stevens)
30-Sep-04 RMS Comment and formating changes based on vax_octa.c 30-Sep-04 RMS Comment and formating changes based on vax_octa.c
18-Apr-04 RMS Moved format definitions to vax_defs.h 18-Apr-04 RMS Moved format definitions to vax_defs.h
@ -93,8 +104,8 @@ void unpackg (int32 hi, int32 lo, UFP *a);
void norm (UFP *a); void norm (UFP *a);
int32 rpackfd (UFP *a, int32 *rh); int32 rpackfd (UFP *a, int32 *rh);
int32 rpackg (UFP *a, int32 *rh); int32 rpackg (UFP *a, int32 *rh);
void vax_fadd (UFP *a, UFP *b, t_int64 mask); void vax_fadd (UFP *a, UFP *b);
void vax_fmul (UFP *a, UFP *b, int32 prec, int32 bias, t_int64 mask); void vax_fmul (UFP *a, UFP *b, t_bool qd, int32 bias, uint32 mhi, uint32 mlo);
void vax_fdiv (UFP *b, UFP *a, int32 prec, int32 bias); void vax_fdiv (UFP *b, UFP *a, int32 prec, int32 bias);
void vax_fmod (UFP *a, int32 bias, int32 *intgr, int32 *flg); void vax_fmod (UFP *a, int32 bias, int32 *intgr, int32 *flg);
@ -285,7 +296,7 @@ UFP a, b;
unpackf (opnd[0], &a); /* unpack operands */ unpackf (opnd[0], &a); /* unpack operands */
unpackf (opnd[2], &b); unpackf (opnd[2], &b);
a.frac = a.frac | (((t_uint64) opnd[1]) << 32); /* extend src1 */ a.frac = a.frac | (((t_uint64) opnd[1]) << 32); /* extend src1 */
vax_fmul (&a, &b, 32, FD_BIAS, LMASK); /* multiply */ vax_fmul (&a, &b, 0, FD_BIAS, 0, LMASK); /* multiply */
vax_fmod (&a, FD_BIAS, intgr, flg); /* sep int & frac */ vax_fmod (&a, FD_BIAS, intgr, flg); /* sep int & frac */
return rpackfd (&a, NULL); /* return frac */ return rpackfd (&a, NULL); /* return frac */
} }
@ -297,7 +308,7 @@ UFP a, b;
unpackd (opnd[0], opnd[1], &a); /* unpack operands */ unpackd (opnd[0], opnd[1], &a); /* unpack operands */
unpackd (opnd[3], opnd[4], &b); unpackd (opnd[3], opnd[4], &b);
a.frac = a.frac | opnd[2]; /* extend src1 */ a.frac = a.frac | opnd[2]; /* extend src1 */
vax_fmul (&a, &b, 64, FD_BIAS, 0); /* multiply */ vax_fmul (&a, &b, 1, FD_BIAS, 0, 0); /* multiply */
vax_fmod (&a, FD_BIAS, intgr, flg); /* sep int & frac */ vax_fmod (&a, FD_BIAS, intgr, flg); /* sep int & frac */
return rpackfd (&a, flo); /* return frac */ return rpackfd (&a, flo); /* return frac */
} }
@ -309,23 +320,23 @@ UFP a, b;
unpackg (opnd[0], opnd[1], &a); /* unpack operands */ unpackg (opnd[0], opnd[1], &a); /* unpack operands */
unpackg (opnd[3], opnd[4], &b); unpackg (opnd[3], opnd[4], &b);
a.frac = a.frac | (opnd[2] >> 5); /* extend src1 */ a.frac = a.frac | (opnd[2] >> 5); /* extend src1 */
vax_fmul (&a, &b, 64, G_BIAS, 0); /* multiply */ vax_fmul (&a, &b, 1, G_BIAS, 0, 0); /* multiply */
vax_fmod (&a, G_BIAS, intgr, flg); /* sep int & frac */ vax_fmod (&a, G_BIAS, intgr, flg); /* sep int & frac */
return rpackg (&a, flo); /* return frac */ return rpackg (&a, flo); /* return frac */
} }
/* Unpacked floating point routines */ /* Unpacked floating point routines */
void vax_fadd (UFP *a, UFP *b, t_int64 mask) void vax_fadd (UFP *a, UFP *b)
{ {
int32 ediff; int32 ediff;
UFP t; UFP t;
if (a->exp == 0) { /* s1 = 0? */ if (a->frac == 0) { /* s1 = 0? */
*a = *b; *a = *b;
return; return;
} }
if (b->exp == 0) return; /* s2 = 0? */ if (b->frac == 0) return; /* s2 = 0? */
if ((a->exp < b->exp) || /* |s1| < |s2|? swap */ if ((a->exp < b->exp) || /* |s1| < |s2|? swap */
((a->exp == b->exp) && (a->frac < b->frac))) { ((a->exp == b->exp) && (a->frac < b->frac))) {
t = *a; t = *a;
@ -341,7 +352,6 @@ if (a->sign ^ b->sign) { /* eff sub? */
a->frac = a->frac + b->frac; /* add frac */ a->frac = a->frac + b->frac; /* add frac */
} }
else a->frac = a->frac - b->frac; /* sub frac */ else a->frac = a->frac - b->frac; /* sub frac */
a->frac = a->frac & ~mask;
norm (a); /* normalize */ norm (a); /* normalize */
} }
else { else {
@ -352,16 +362,16 @@ else {
a->frac = UF_NM | (a->frac >> 1); /* shift in carry */ a->frac = UF_NM | (a->frac >> 1); /* shift in carry */
a->exp = a->exp + 1; /* skip norm */ a->exp = a->exp + 1; /* skip norm */
} }
a->frac = a->frac & ~mask;
} }
return; return;
} }
/* Floating multiply - 64b * 64b with cross products */ /* Floating multiply - 64b * 64b with cross products */
void vax_fmul (UFP *a, UFP *b, int32 prec, int32 bias, t_int64 mask) void vax_fmul (UFP *a, UFP *b, t_bool qd, int32 bias, uint32 mhi, uint32 mlo)
{ {
t_uint64 ah, bh, al, bl, rhi, rlo, rmid1, rmid2; t_uint64 ah, bh, al, bl, rhi, rlo, rmid1, rmid2;
t_uint64 mask = (((t_uint64) mhi) << 32) | ((t_uint64) mlo);
if ((a->exp == 0) || (b->exp == 0)) { /* zero argument? */ if ((a->exp == 0) || (b->exp == 0)) { /* zero argument? */
a->frac = a->sign = a->exp = 0; /* result is zero */ a->frac = a->sign = a->exp = 0; /* result is zero */
@ -372,7 +382,7 @@ a->exp = a->exp + b->exp - bias; /* add exponents */
ah = (a->frac >> 32) & LMASK; /* split operands */ ah = (a->frac >> 32) & LMASK; /* split operands */
bh = (b->frac >> 32) & LMASK; /* into 32b chunks */ bh = (b->frac >> 32) & LMASK; /* into 32b chunks */
rhi = ah * bh; /* high result */ rhi = ah * bh; /* high result */
if (prec > 32) { /* 64b needed? */ if (qd) { /* 64b needed? */
al = a->frac & LMASK; al = a->frac & LMASK;
bl = b->frac & LMASK; bl = b->frac & LMASK;
rmid1 = ah * bl; rmid1 = ah * bl;
@ -381,10 +391,10 @@ if (prec > 32) { /* 64b needed? */
rhi = rhi + ((rmid1 >> 32) & LMASK) + ((rmid2 >> 32) & LMASK); rhi = rhi + ((rmid1 >> 32) & LMASK) + ((rmid2 >> 32) & LMASK);
rmid1 = rlo + (rmid1 << 32); /* add mid1 to lo */ rmid1 = rlo + (rmid1 << 32); /* add mid1 to lo */
if (rmid1 < rlo) rhi = rhi + 1; /* carry? incr hi */ if (rmid1 < rlo) rhi = rhi + 1; /* carry? incr hi */
rmid2 = rmid1 + (rmid2 << 32); /* add mid2 to to */ rmid2 = rmid1 + (rmid2 << 32); /* add mid2 to lo */
if (rmid2 < rmid1) rhi = rhi + 1; /* carry? incr hi */ if (rmid2 < rmid1) rhi = rhi + 1; /* carry? incr hi */
} }
a->frac = rhi & ~mask; /* mask out */ a->frac = rhi & ~mask;
norm (a); /* normalize */ norm (a); /* normalize */
return; return;
} }
@ -402,7 +412,7 @@ return;
void vax_fmod (UFP *a, int32 bias, int32 *intgr, int32 *flg) void vax_fmod (UFP *a, int32 bias, int32 *intgr, int32 *flg)
{ {
if (a->exp <= bias) *intgr = *flg = 0; /* 0 or <1? int = 0 */ if (a->exp <= bias) *intgr = *flg = 0; /* 0 or <1? int = 0 */
else if (a->exp <= (bias + 64)) { /* in range? */ else if (a->exp <= (bias + 64)) { /* in range [1,64]? */
*intgr = (int32) (a->frac >> (64 - (a->exp - bias))); *intgr = (int32) (a->frac >> (64 - (a->exp - bias)));
if ((a->exp > (bias + 32)) || /* test ovflo */ if ((a->exp > (bias + 32)) || /* test ovflo */
((a->exp == (bias + 32)) && ((a->exp == (bias + 32)) &&
@ -410,7 +420,8 @@ else if (a->exp <= (bias + 64)) { /* in range? */
*flg = CC_V; *flg = CC_V;
else *flg = 0; else *flg = 0;
if (a->sign) *intgr = -*intgr; /* -? comp int */ if (a->sign) *intgr = -*intgr; /* -? comp int */
a->frac = a->frac << (a->exp - bias); if (a->exp == (bias + 64)) a->frac = 0; /* special case 64 */
else a->frac = a->frac << (a->exp - bias);
a->exp = bias; a->exp = bias;
} }
else { else {
@ -585,11 +596,10 @@ void unpackg (uint32 hi, uint32 lo, UFP *a);
void norm (UFP *a); void norm (UFP *a);
int32 rpackfd (UFP *a, int32 *rh); int32 rpackfd (UFP *a, int32 *rh);
int32 rpackg (UFP *a, int32 *rh); int32 rpackg (UFP *a, int32 *rh);
void vax_fadd (UFP *a, UFP *b, uint32 mask); void vax_fadd (UFP *a, UFP *b);
void vax_fmul (UFP *a, UFP *b, int32 prec, int32 bias, uint32 mask); void vax_fmul (UFP *a, UFP *b, t_bool qd, int32 bias, uint32 mhi, uint32 mlo);
void vax_fmod (UFP *a, int32 bias, int32 *intgr, int32 *flg); void vax_fmod (UFP *a, int32 bias, int32 *intgr, int32 *flg);
void vax_fdiv (UFP *b, UFP *a, int32 prec, int32 bias); void vax_fdiv (UFP *b, UFP *a, int32 prec, int32 bias);
int32 vax_fcmp (UFP *a, UFP *b);
void dp_add (UDP *a, UDP *b); void dp_add (UDP *a, UDP *b);
void dp_inc (UDP *a); void dp_inc (UDP *a);
void dp_sub (UDP *a, UDP *b); void dp_sub (UDP *a, UDP *b);
@ -787,7 +797,7 @@ UFP a, b;
unpackf (opnd[0], &a); /* unpack operands */ unpackf (opnd[0], &a); /* unpack operands */
unpackf (opnd[2], &b); unpackf (opnd[2], &b);
a.frac.hi = a.frac.hi | opnd[1]; /* extend src1 */ a.frac.hi = a.frac.hi | opnd[1]; /* extend src1 */
vax_fmul (&a, &b, 32, FD_BIAS, LMASK); /* multiply */ vax_fmul (&a, &b, 0, FD_BIAS, 0, LMASK); /* multiply */
vax_fmod (&a, FD_BIAS, intgr, flg); /* sep int & frac */ vax_fmod (&a, FD_BIAS, intgr, flg); /* sep int & frac */
return rpackfd (&a, NULL); /* return frac */ return rpackfd (&a, NULL); /* return frac */
} }
@ -799,7 +809,7 @@ UFP a, b;
unpackd (opnd[0], opnd[1], &a); /* unpack operands */ unpackd (opnd[0], opnd[1], &a); /* unpack operands */
unpackd (opnd[3], opnd[4], &b); unpackd (opnd[3], opnd[4], &b);
a.frac.lo = a.frac.lo | opnd[2]; /* extend src1 */ a.frac.lo = a.frac.lo | opnd[2]; /* extend src1 */
vax_fmul (&a, &b, 64, FD_BIAS, 0); /* multiply */ vax_fmul (&a, &b, 1, FD_BIAS, 0, 0); /* multiply */
vax_fmod (&a, FD_BIAS, intgr, flg); /* sep int & frac */ vax_fmod (&a, FD_BIAS, intgr, flg); /* sep int & frac */
return rpackfd (&a, flo); /* return frac */ return rpackfd (&a, flo); /* return frac */
} }
@ -811,7 +821,7 @@ UFP a, b;
unpackg (opnd[0], opnd[1], &a); /* unpack operands */ unpackg (opnd[0], opnd[1], &a); /* unpack operands */
unpackg (opnd[3], opnd[4], &b); unpackg (opnd[3], opnd[4], &b);
a.frac.lo = a.frac.lo | (opnd[2] >> 5); /* extend src1 */ a.frac.lo = a.frac.lo | (opnd[2] >> 5); /* extend src1 */
vax_fmul (&a, &b, 64, G_BIAS, 0); /* multiply */ vax_fmul (&a, &b, 1, G_BIAS, 0, 0); /* multiply */
vax_fmod (&a, G_BIAS, intgr, flg); /* sep int & frac */ vax_fmod (&a, G_BIAS, intgr, flg); /* sep int & frac */
return rpackg (&a, flo); /* return frac */ return rpackg (&a, flo); /* return frac */
} }
@ -820,16 +830,16 @@ return rpackg (&a, flo); /* return frac */
/* Floating add */ /* Floating add */
void vax_fadd (UFP *a, UFP *b, uint32 mask) void vax_fadd (UFP *a, UFP *b)
{ {
int32 ediff; int32 ediff;
UFP t; UFP t;
if (a->exp == 0) { /* s1 = 0? */ if ((a->frac.hi == 0) && (a->frac.lo == 0)) { /* s1 = 0? */
*a = *b; *a = *b;
return; return;
} }
if (b->exp == 0) return; /* s2 = 0? */ if ((b->frac.hi == 0) && (b->frac.lo == 0)) return; /* s2 = 0? */
if ((a->exp < b->exp) || /* |s1| < |s2|? swap */ if ((a->exp < b->exp) || /* |s1| < |s2|? swap */
((a->exp == b->exp) && (dp_cmp (&a->frac, &b->frac) < 0))) { ((a->exp == b->exp) && (dp_cmp (&a->frac, &b->frac) < 0))) {
t = *a; t = *a;
@ -844,7 +854,6 @@ if (a->sign ^ b->sign) { /* eff sub? */
dp_add (&a->frac, &b->frac); /* "add" frac */ dp_add (&a->frac, &b->frac); /* "add" frac */
} }
else dp_sub (&a->frac, &b->frac); /* a >= b */ else dp_sub (&a->frac, &b->frac); /* a >= b */
a->frac.lo = a->frac.lo & ~mask; /* trim low result */
norm (a); /* normalize */ norm (a); /* normalize */
} }
else { else {
@ -855,28 +864,13 @@ else {
a->frac.hi = a->frac.hi | UF_NM_H; /* add norm bit */ a->frac.hi = a->frac.hi | UF_NM_H; /* add norm bit */
a->exp = a->exp + 1; /* skip norm */ a->exp = a->exp + 1; /* skip norm */
} }
a->frac.lo = a->frac.lo & ~mask; /* trim low result */
} }
return; return;
} }
/* Floating compare */
int32 vax_fcmp (UFP *a, UFP *b)
{
int32 r;
if (a->sign != b->sign) return ((a->sign)? CC_N: 0);
r = a->exp - b->exp;
if (r == 0) r = dp_cmp (&a->frac, &b->frac);
if (r == 0) return CC_Z;
if (r < 0) return (a->sign? 0: CC_N);
else return (a->sign? CC_N: 0);
}
/* Floating multiply - 64b * 64b with cross products */ /* Floating multiply - 64b * 64b with cross products */
void vax_fmul (UFP *a, UFP *b, int32 prec, int32 bias, uint32 mask) void vax_fmul (UFP *a, UFP *b, t_bool qd, int32 bias, uint32 mhi, uint32 mlo)
{ {
UDP rhi, rlo, rmid1, rmid2; UDP rhi, rlo, rmid1, rmid2;
@ -888,7 +882,7 @@ if ((a->exp == 0) || (b->exp == 0)) { /* zero argument? */
a->sign = a->sign ^ b->sign; /* sign of result */ a->sign = a->sign ^ b->sign; /* sign of result */
a->exp = a->exp + b->exp - bias; /* add exponents */ a->exp = a->exp + b->exp - bias; /* add exponents */
dp_imul (a->frac.hi, b->frac.hi, &rhi); /* high result */ dp_imul (a->frac.hi, b->frac.hi, &rhi); /* high result */
if (prec > 32) { /* 64b needed? */ if (qd) { /* 64b needed? */
dp_imul (a->frac.hi, b->frac.lo, &rmid1); /* cross products */ dp_imul (a->frac.hi, b->frac.lo, &rmid1); /* cross products */
dp_imul (a->frac.lo, b->frac.hi, &rmid2); dp_imul (a->frac.lo, b->frac.hi, &rmid2);
dp_imul (a->frac.lo, b->frac.lo, &rlo); /* low result */ dp_imul (a->frac.lo, b->frac.lo, &rlo); /* low result */
@ -901,10 +895,10 @@ if (prec > 32) { /* 64b needed? */
rlo.hi = (rlo.hi + rmid1.lo) & LMASK; /* add mid1 to low res */ rlo.hi = (rlo.hi + rmid1.lo) & LMASK; /* add mid1 to low res */
if (rlo.hi < rmid1.lo) dp_inc (&rhi); /* carry? incr high res */ if (rlo.hi < rmid1.lo) dp_inc (&rhi); /* carry? incr high res */
rlo.hi = (rlo.hi + rmid2.lo) & LMASK; /* add mid2 to low res */ rlo.hi = (rlo.hi + rmid2.lo) & LMASK; /* add mid2 to low res */
if (rlo.hi < rmid1.hi) dp_inc (&rhi); /* carry? incr high res */ if (rlo.hi < rmid2.lo) dp_inc (&rhi); /* carry? incr high res */
} }
a->frac.hi = rhi.hi; /* mask low fraction */ a->frac.hi = rhi.hi & ~mhi; /* mask fraction */
a->frac.lo = rhi.lo & ~mask; a->frac.lo = rhi.lo & ~mlo;
norm (a); /* normalize */ norm (a); /* normalize */
return; return;
} }
@ -924,7 +918,7 @@ void vax_fmod (UFP *a, int32 bias, int32 *intgr, int32 *flg)
UDP ifr; UDP ifr;
if (a->exp <= bias) *intgr = *flg = 0; /* 0 or <1? int = 0 */ if (a->exp <= bias) *intgr = *flg = 0; /* 0 or <1? int = 0 */
else if (a->exp <= (bias + 64)) { /* in range? */ else if (a->exp <= (bias + 64)) { /* in range [1,64]? */
ifr = a->frac; ifr = a->frac;
dp_rsh (&ifr, 64 - (a->exp - bias)); /* separate integer */ dp_rsh (&ifr, 64 - (a->exp - bias)); /* separate integer */
if ((a->exp > (bias + 32)) || /* test ovflo */ if ((a->exp > (bias + 32)) || /* test ovflo */
@ -1073,7 +1067,7 @@ rlo = al * bl;
rhi = rhi + ((rmid1 >> 16) & WMASK) + ((rmid2 >> 16) & WMASK); rhi = rhi + ((rmid1 >> 16) & WMASK) + ((rmid2 >> 16) & WMASK);
rmid1 = (rlo + (rmid1 << 16)) & LMASK; /* add mid1 to lo */ rmid1 = (rlo + (rmid1 << 16)) & LMASK; /* add mid1 to lo */
if (rmid1 < rlo) rhi = rhi + 1; /* carry? incr hi */ if (rmid1 < rlo) rhi = rhi + 1; /* carry? incr hi */
rmid2 = (rmid1 + (rmid2 << 16)) & LMASK; /* add mid2 to to */ rmid2 = (rmid1 + (rmid2 << 16)) & LMASK; /* add mid2 to to */
if (rmid2 < rmid1) rhi = rhi + 1; /* carry? incr hi */ if (rmid2 < rmid1) rhi = rhi + 1; /* carry? incr hi */
r->hi = rhi & LMASK; /* mask result */ r->hi = rhi & LMASK; /* mask result */
r->lo = rmid2; r->lo = rmid2;
@ -1277,7 +1271,7 @@ UFP a, b;
unpackf (opnd[0], &a); /* F format */ unpackf (opnd[0], &a); /* F format */
unpackf (opnd[1], &b); unpackf (opnd[1], &b);
if (sub) a.sign = a.sign ^ FPSIGN; /* sub? -s1 */ if (sub) a.sign = a.sign ^ FPSIGN; /* sub? -s1 */
vax_fadd (&a, &b, 0); /* add fractions */ vax_fadd (&a, &b); /* add fractions */
return rpackfd (&a, NULL); return rpackfd (&a, NULL);
} }
@ -1288,7 +1282,7 @@ UFP a, b;
unpackd (opnd[0], opnd[1], &a); unpackd (opnd[0], opnd[1], &a);
unpackd (opnd[2], opnd[3], &b); unpackd (opnd[2], opnd[3], &b);
if (sub) a.sign = a.sign ^ FPSIGN; /* sub? -s1 */ if (sub) a.sign = a.sign ^ FPSIGN; /* sub? -s1 */
vax_fadd (&a, &b, 0); /* add fractions */ vax_fadd (&a, &b); /* add fractions */
return rpackfd (&a, rh); return rpackfd (&a, rh);
} }
@ -1299,7 +1293,7 @@ UFP a, b;
unpackg (opnd[0], opnd[1], &a); unpackg (opnd[0], opnd[1], &a);
unpackg (opnd[2], opnd[3], &b); unpackg (opnd[2], opnd[3], &b);
if (sub) a.sign = a.sign ^ FPSIGN; /* sub? -s1 */ if (sub) a.sign = a.sign ^ FPSIGN; /* sub? -s1 */
vax_fadd (&a, &b, 0); /* add fractions */ vax_fadd (&a, &b); /* add fractions */
return rpackg (&a, rh); /* round and pack */ return rpackg (&a, rh); /* round and pack */
} }
@ -1311,7 +1305,7 @@ UFP a, b;
unpackf (opnd[0], &a); /* F format */ unpackf (opnd[0], &a); /* F format */
unpackf (opnd[1], &b); unpackf (opnd[1], &b);
vax_fmul (&a, &b, 24, FD_BIAS, 0); /* do multiply */ vax_fmul (&a, &b, 0, FD_BIAS, 0, 0); /* do multiply */
return rpackfd (&a, NULL); /* round and pack */ return rpackfd (&a, NULL); /* round and pack */
} }
@ -1319,9 +1313,9 @@ int32 op_muld (int32 *opnd, int32 *rh)
{ {
UFP a, b; UFP a, b;
unpackd (opnd[0], opnd[1], &a); unpackd (opnd[0], opnd[1], &a); /* D format */
unpackd (opnd[2], opnd[3], &b); unpackd (opnd[2], opnd[3], &b);
vax_fmul (&a, &b, 56, FD_BIAS, 0); /* do multiply */ vax_fmul (&a, &b, 1, FD_BIAS, 0, 0); /* do multiply */
return rpackfd (&a, rh); /* round and pack */ return rpackfd (&a, rh); /* round and pack */
} }
@ -1331,7 +1325,7 @@ UFP a, b;
unpackg (opnd[0], opnd[1], &a); /* G format */ unpackg (opnd[0], opnd[1], &a); /* G format */
unpackg (opnd[2], opnd[3], &b); unpackg (opnd[2], opnd[3], &b);
vax_fmul (&a, &b, 53, G_BIAS, 0); /* do multiply */ vax_fmul (&a, &b, 1, G_BIAS, 0, 0); /* do multiply */
return rpackg (&a, rh); /* round and pack */ return rpackg (&a, rh); /* round and pack */
} }
@ -1351,7 +1345,7 @@ int32 op_divd (int32 *opnd, int32 *rh)
{ {
UFP a, b; UFP a, b;
unpackd (opnd[0], opnd[1], &a); unpackd (opnd[0], opnd[1], &a); /* D format */
unpackd (opnd[2], opnd[3], &b); unpackd (opnd[2], opnd[3], &b);
vax_fdiv (&a, &b, 58, FD_BIAS); /* do divide */ vax_fdiv (&a, &b, 58, FD_BIAS); /* do divide */
return rpackfd (&b, rh); /* round and pack */ return rpackfd (&b, rh); /* round and pack */
@ -1370,9 +1364,9 @@ return rpackg (&b, rh); /* round and pack */
/* Polynomial evaluation /* Polynomial evaluation
The most mis-implemented instruction in the VAX (probably here too). The most mis-implemented instruction in the VAX (probably here too).
POLY requires a precise combination of masking versus normalizing POLY requires a precise combination of masking versus normalizing
to achieve the desired answer. In particular, both the multiply to achieve the desired answer. In particular, the multiply step
and add steps are masked prior to normalization. In addition, is masked prior to normalization. In addition, negative small
negative small fractions must not be treated as 0 during denorm. fractions must not be treated as 0 during denorm.
*/ */
void op_polyf (int32 *opnd, int32 acc) void op_polyf (int32 *opnd, int32 acc)
@ -1388,18 +1382,18 @@ wd = Read (ptr, L_LONG, RD); /* get C0 */
ptr = ptr + 4; ptr = ptr + 4;
unpackf (wd, &r); /* unpack C0 */ unpackf (wd, &r); /* unpack C0 */
res = rpackfd (&r, NULL); /* first result */ res = rpackfd (&r, NULL); /* first result */
for (i = 0; (i < deg) && a.exp; i++) { /* loop */ for (i = 0; i < deg; i++) { /* loop */
unpackf (res, &r); /* unpack result */ unpackf (res, &r); /* unpack result */
vax_fmul (&r, &a, 32, FD_BIAS, LMASK); /* r = r * arg */ vax_fmul (&r, &a, 0, FD_BIAS, 1, LMASK); /* r = r * arg, mask */
wd = Read (ptr, L_LONG, RD); /* get Cnext */ wd = Read (ptr, L_LONG, RD); /* get Cnext */
ptr = ptr + 4; ptr = ptr + 4;
unpackf (wd, &c); /* unpack Cnext */ unpackf (wd, &c); /* unpack Cnext */
vax_fadd (&r, &c, LMASK); /* r = r + Cnext */ vax_fadd (&r, &c); /* r = r + Cnext */
res = rpackfd (&r, NULL); /* round and pack */ res = rpackfd (&r, NULL); /* round and pack */
} }
R[0] = res; R[0] = res;
R[1] = R[2] = 0; R[1] = R[2] = 0;
R[3] = opnd[2] + 4 + (opnd[1] << 2); R[3] = ptr;
return; return;
} }
@ -1417,20 +1411,22 @@ wd1 = Read (ptr + 4, L_LONG, RD);
ptr = ptr + 8; ptr = ptr + 8;
unpackd (wd, wd1, &r); /* unpack C0 */ unpackd (wd, wd1, &r); /* unpack C0 */
res = rpackfd (&r, &resh); /* first result */ res = rpackfd (&r, &resh); /* first result */
for (i = 0; (i < deg) && a.exp; i++) { /* loop */ for (i = 0; i < deg; i++) { /* loop */
unpackd (res, resh, &r); /* unpack result */ unpackd (res, resh, &r); /* unpack result */
vax_fmul (&r, &a, 32, FD_BIAS, 0); /* r = r * arg */ vax_fmul (&r, &a, 1, FD_BIAS, 0, 1); /* r = r * arg, mask */
wd = Read (ptr, L_LONG, RD); /* get Cnext */ wd = Read (ptr, L_LONG, RD); /* get Cnext */
wd1 = Read (ptr + 4, L_LONG, RD); wd1 = Read (ptr + 4, L_LONG, RD);
ptr = ptr + 8; ptr = ptr + 8;
unpackd (wd, wd1, &c); /* unpack Cnext */ unpackd (wd, wd1, &c); /* unpack Cnext */
vax_fadd (&r, &c, 0); /* r = r + Cnext */ vax_fadd (&r, &c); /* r = r + Cnext */
res = rpackfd (&r, &resh); /* round and pack */ res = rpackfd (&r, &resh); /* round and pack */
} }
R[0] = res; R[0] = res;
R[1] = resh; R[1] = resh;
R[2] = 0; R[2] = 0;
R[3] = opnd[3] + 4 + (opnd[2] << 2); R[3] = ptr;
R[4] = 0;
R[5] = 0;
return; return;
} }
@ -1448,19 +1444,21 @@ wd1 = Read (ptr + 4, L_LONG, RD);
ptr = ptr + 8; ptr = ptr + 8;
unpackg (wd, wd1, &r); /* unpack C0 */ unpackg (wd, wd1, &r); /* unpack C0 */
res = rpackg (&r, &resh); /* first result */ res = rpackg (&r, &resh); /* first result */
for (i = 0; (i < deg) && a.exp; i++) { /* loop */ for (i = 0; i < deg; i++) { /* loop */
unpackg (res, resh, &r); /* unpack result */ unpackg (res, resh, &r); /* unpack result */
vax_fmul (&r, &a, 32, G_BIAS, 0); /* r = r * arg */ vax_fmul (&r, &a, 1, G_BIAS, 0, 1); /* r = r * arg */
wd = Read (ptr, L_LONG, RD); /* get Cnext */ wd = Read (ptr, L_LONG, RD); /* get Cnext */
wd1 = Read (ptr + 4, L_LONG, RD); wd1 = Read (ptr + 4, L_LONG, RD);
ptr = ptr + 8; ptr = ptr + 8;
unpackg (wd, wd1, &c); /* unpack Cnext */ unpackg (wd, wd1, &c); /* unpack Cnext */
vax_fadd (&r, &c, 0); /* r = r + Cnext */ vax_fadd (&r, &c); /* r = r + Cnext */
res = rpackg (&r, &resh); /* round and pack */ res = rpackg (&r, &resh); /* round and pack */
} }
R[0] = res; R[0] = res;
R[1] = resh; R[1] = resh;
R[2] = 0; R[2] = 0;
R[3] = opnd[3] + 4 + (opnd[2] << 2); R[3] = ptr;
R[4] = 0;
R[5] = 0;
return; return;
} }

View file

@ -151,13 +151,15 @@ DEVICE tlb_dev = {
3. Using the two physical addresses, do an unaligned read or 3. Using the two physical addresses, do an unaligned read or
write, with three cases: unaligned long, unaligned word within write, with three cases: unaligned long, unaligned word within
a longword, unaligned word crossing a longword boundary. a longword, unaligned word crossing a longword boundary.
Note that these routines do not handle quad or octa references.
*/ */
/* Read virtual /* Read virtual
Inputs: Inputs:
va = virtual address va = virtual address
lnt = length code (BWLQ) lnt = length code (BWL)
acc = access code (KESU) acc = access code (KESU)
Output: Output:
returned data, right justified in 32b longword returned data, right justified in 32b longword
@ -216,7 +218,7 @@ else {
Inputs: Inputs:
va = virtual address va = virtual address
val = data to be written, right justified in 32b lw val = data to be written, right justified in 32b lw
lnt = length code (BWLQ) lnt = length code (BWL)
acc = access code (KESU) acc = access code (KESU)
Output: Output:
none none
@ -440,7 +442,8 @@ int32 tlbpte, ptead, pte, tbi, vpn;
static TLBENT zero_pte = { 0, 0 }; static TLBENT zero_pte = { 0, 0 };
if (va & VA_S0) { /* system space? */ if (va & VA_S0) { /* system space? */
if (ptidx >= d_slr) MM_ERR (PR_LNV); /* system */ if (ptidx >= d_slr) /* system */
MM_ERR (PR_LNV);
ptead = d_sbr + ptidx; ptead = d_sbr + ptidx;
} }
else { else {
@ -458,8 +461,12 @@ else {
tbi = VA_GETTBI (vpn); tbi = VA_GETTBI (vpn);
if (stlb[tbi].tag != vpn) { /* in sys tlb? */ if (stlb[tbi].tag != vpn) { /* in sys tlb? */
ptidx = ((uint32) ptead) >> 7; /* xlate like sys */ ptidx = ((uint32) ptead) >> 7; /* xlate like sys */
if (ptidx >= d_slr) MM_ERR (PR_PLNV); if (ptidx >= d_slr)
MM_ERR (PR_PLNV);
pte = ReadLP (d_sbr + ptidx); /* get system pte */ pte = ReadLP (d_sbr + ptidx); /* get system pte */
#if defined (VAX_780)
if ((pte & PTE_ACC) == 0) MM_ERR (PR_PACV); /* spte ACV? */
#endif
if ((pte & PTE_V) == 0) MM_ERR (PR_PTNV); /* spte TNV? */ if ((pte & PTE_V) == 0) MM_ERR (PR_PTNV); /* spte TNV? */
stlb[tbi].tag = vpn; /* set stlb tag */ stlb[tbi].tag = vpn; /* set stlb tag */
stlb[tbi].pte = cvtacc[PTE_GETACC (pte)] | stlb[tbi].pte = cvtacc[PTE_GETACC (pte)] |

View file

@ -1,6 +1,6 @@
/* vax_octa.c - VAX octaword and h_floating instructions /* vax_octa.c - VAX octaword and h_floating instructions
Copyright (c) 2004-2005, Robert M Supnik Copyright (c) 2004-2006, Robert M Supnik
Permission is hereby granted, free of charge, to any person obtaining a Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"), copy of this software and associated documentation files (the "Software"),
@ -25,6 +25,18 @@
This module simulates the VAX h_floating instruction set. This module simulates the VAX h_floating instruction set.
10-May-06 RMS Fixed bug in reported VA on faulting cross-page write
03-May-06 RMS Fixed MNEGH to test negated sign, clear C
Fixed carry propagation in qp_inc, qp_neg, qp_add
Fixed pack routines to test for zero via fraction
Fixed ACBH to set cc's on result
Fixed POLYH to set R3 correctly
Fixed POLYH to not exit prematurely if arg = 0
Fixed POLYH to mask mul reslt to 127b
Fixed fp add routine to test for zero via fraction
to support "denormal" argument from POLYH
Fixed EMODH to concatenate 15b of 16b extension
(all reported by Tim Stark)
15-Jul-04 RMS Cloned from 32b VAX floating point implementation 15-Jul-04 RMS Cloned from 32b VAX floating point implementation
*/ */
@ -54,7 +66,7 @@ typedef struct {
typedef struct { typedef struct {
int32 sign; int32 sign;
int32 exp; int32 exp;
UQP frac; UQP frac;
} UFPH; } UFPH;
#define UH_NM_H 0x80000000 /* normalized */ #define UH_NM_H 0x80000000 /* normalized */
@ -83,10 +95,11 @@ void h_write_l (int32 spec, int32 va, int32 val, int32 acc);
void h_write_q (int32 spec, int32 va, int32 vl, int32 vh, int32 acc); void h_write_q (int32 spec, int32 va, int32 vl, int32 vh, int32 acc);
void h_write_o (int32 spec, int32 va, int32 *val, int32 acc); void h_write_o (int32 spec, int32 va, int32 *val, int32 acc);
void vax_hadd (UFPH *a, UFPH *b); void vax_hadd (UFPH *a, UFPH *b);
void vax_hmul (UFPH *a, UFPH *b); void vax_hmul (UFPH *a, UFPH *b, uint32 mlo);
void vax_hmod (UFPH *a, int32 *intgr, int32 *flg); void vax_hmod (UFPH *a, int32 *intgr, int32 *flg);
void vax_hdiv (UFPH *a, UFPH *b); void vax_hdiv (UFPH *a, UFPH *b);
void qp_add (UQP *a, UQP *b); uint32 qp_add (UQP *a, UQP *b);
uint32 qp_sub (UQP *a, UQP *b);
void qp_inc (UQP *a); void qp_inc (UQP *a);
void qp_lsh (UQP *a, uint32 sc); void qp_lsh (UQP *a, uint32 sc);
void qp_rsh (UQP *a, uint32 sc); void qp_rsh (UQP *a, uint32 sc);
@ -172,19 +185,26 @@ switch (opc) {
break; break;
case MOVH: case MOVH:
if (r = op_tsth (opnd[0])) /* test for 0 */ if (r = op_tsth (opnd[0])) { /* test for 0 */
h_write_o (spec, va, opnd, acc); /* nz, write result */ h_write_o (spec, va, opnd, acc); /* nz, write result */
else h_write_o (spec, va, z_octa, acc); /* zero, write 0 */ CC_IIZP_FP (r); /* set cc's */
CC_IIZP_FP (r); /* set cc's */ }
else { /* zero */
h_write_o (spec, va, z_octa, acc); /* write 0 */
cc = (cc & CC_C) | CC_Z; /* set cc's */
}
break; break;
case MNEGH: case MNEGH:
if (r = op_tsth (opnd[0])) { /* test for 0 */ if (r = op_tsth (opnd[0])) { /* test for 0 */
opnd[0] = opnd[0] ^ FPSIGN; /* nz, invert sign */ opnd[0] = opnd[0] ^ FPSIGN; /* nz, invert sign */
h_write_o (spec, va, opnd, acc); /* write result */ h_write_o (spec, va, opnd, acc); /* write result */
CC_IIZZ_FP (opnd[0]); /* set cc's */
}
else { /* zero */
h_write_o (spec, va, z_octa, acc); /* write 0 */
cc = CC_Z; /* set cc's */
} }
else h_write_o (spec, va, z_octa, acc); /* zero, write 0 */
CC_IIZZ_FP (r); /* set cc's */
break; break;
/* CMPH /* CMPH
@ -365,6 +385,7 @@ switch (opc) {
case ACBH: case ACBH:
r = op_addh (opnd + 4, r_octa, FALSE); /* add + index */ r = op_addh (opnd + 4, r_octa, FALSE); /* add + index */
CC_IIZP_FP (r); /* set cc's */
temp = op_cmph (r_octa, opnd); /* result : limit */ temp = op_cmph (r_octa, opnd); /* result : limit */
h_write_o (spec, va, r_octa, acc); /* write 2nd */ h_write_o (spec, va, r_octa, acc); /* write 2nd */
if ((temp & CC_Z) || ((opnd[4] & FPSIGN)? /* test br cond */ if ((temp & CC_Z) || ((opnd[4] & FPSIGN)? /* test br cond */
@ -501,7 +522,7 @@ int32 op_cvtfdh (int32 vl, int32 vh, int32 *hflt)
UFPH a; UFPH a;
h_unpackfd (vl, vh, &a); /* unpack f/d */ h_unpackfd (vl, vh, &a); /* unpack f/d */
a.exp = a.exp - FD_BIAS + H_BIAS; /* adjust exp */ a.exp = a.exp - FD_BIAS + H_BIAS; /* if nz, adjust exp */
return h_rpackh (&a, hflt); /* round and pack */ return h_rpackh (&a, hflt); /* round and pack */
} }
@ -510,7 +531,7 @@ int32 op_cvtgh (int32 vl, int32 vh, int32 *hflt)
UFPH a; UFPH a;
h_unpackg (vl, vh, &a); /* unpack g */ h_unpackg (vl, vh, &a); /* unpack g */
a.exp = a.exp - G_BIAS + H_BIAS; /* adjust exp */ a.exp = a.exp - G_BIAS + H_BIAS; /* if nz, adjust exp */
return h_rpackh (&a, hflt); /* round and pack */ return h_rpackh (&a, hflt); /* round and pack */
} }
@ -519,7 +540,7 @@ int32 op_cvthfd (int32 *hflt, int32 *rh)
UFPH a; UFPH a;
h_unpackh (hflt, &a); /* unpack h */ h_unpackh (hflt, &a); /* unpack h */
a.exp = a.exp - H_BIAS + FD_BIAS; /* adjust exp */ a.exp = a.exp - H_BIAS + FD_BIAS; /* if nz, adjust exp */
return h_rpackfd (&a, rh); /* round and pack */ return h_rpackfd (&a, rh); /* round and pack */
} }
@ -528,7 +549,7 @@ int32 op_cvthg (int32 *hflt, int32 *rh)
UFPH a; UFPH a;
h_unpackh (hflt, &a); /* unpack h */ h_unpackh (hflt, &a); /* unpack h */
a.exp = a.exp - H_BIAS + G_BIAS; /* adjust exp */ a.exp = a.exp - H_BIAS + G_BIAS; /* if nz, adjust exp */
return h_rpackg (&a, rh); /* round and pack */ return h_rpackg (&a, rh); /* round and pack */
} }
@ -553,7 +574,7 @@ UFPH a, b;
h_unpackh (&opnd[0], &a); /* unpack s1, s2 */ h_unpackh (&opnd[0], &a); /* unpack s1, s2 */
h_unpackh (&opnd[4], &b); h_unpackh (&opnd[4], &b);
vax_hmul (&a, &b); /* do multiply */ vax_hmul (&a, &b, 0); /* do multiply */
return h_rpackh (&a, hflt); /* round and pack */ return h_rpackh (&a, hflt); /* round and pack */
} }
@ -566,7 +587,7 @@ UFPH a, b;
h_unpackh (&opnd[0], &a); /* unpack s1, s2 */ h_unpackh (&opnd[0], &a); /* unpack s1, s2 */
h_unpackh (&opnd[4], &b); h_unpackh (&opnd[4], &b);
vax_hdiv (&a, &b); /* do divide */ vax_hdiv (&a, &b); /* do divide */
return h_rpackh (&a, hflt); /* round and pack */ return h_rpackh (&b, hflt); /* round and pack */
} }
/* Polynomial evaluation /* Polynomial evaluation
@ -593,9 +614,9 @@ wd[3] = Read (ptr + 12, L_LONG, RD);
ptr = ptr + 16; /* adv ptr */ ptr = ptr + 16; /* adv ptr */
h_unpackh (wd, &r); /* unpack C0 */ h_unpackh (wd, &r); /* unpack C0 */
h_rpackh (&r, res); /* first result */ h_rpackh (&r, res); /* first result */
for (i = 0; (i < deg) && a.exp; i++) { /* loop */ for (i = 0; i < deg; i++) { /* loop */
h_unpackh (res, &r); /* unpack result */ h_unpackh (res, &r); /* unpack result */
vax_hmul (&r, &a); /* r = r * arg */ vax_hmul (&r, &a, 1); /* r = r * arg */
wd[0] = Read (ptr, L_LONG, RD); /* get Cn */ wd[0] = Read (ptr, L_LONG, RD); /* get Cn */
wd[1] = Read (ptr + 4, L_LONG, RD); wd[1] = Read (ptr + 4, L_LONG, RD);
wd[2] = Read (ptr + 8, L_LONG, RD); wd[2] = Read (ptr + 8, L_LONG, RD);
@ -610,7 +631,7 @@ R[1] = res[1];
R[2] = res[2]; R[2] = res[2];
R[3] = res[3]; R[3] = res[3];
R[4] = 0; R[4] = 0;
R[5] = opnd[5] + 4 + (opnd[4] << 2); R[5] = ptr;
return; return;
} }
@ -627,8 +648,8 @@ UFPH a, b;
h_unpackh (&opnd[0], &a); /* unpack operands */ h_unpackh (&opnd[0], &a); /* unpack operands */
h_unpackh (&opnd[5], &b); h_unpackh (&opnd[5], &b);
a.frac.f0 = a.frac.f0 | opnd[4]; /* extend src1 */ a.frac.f0 = a.frac.f0 | (opnd[4] >> 1); /* extend src1 */
vax_hmul (&a, &b); /* multiply */ vax_hmul (&a, &b, 0); /* multiply */
vax_hmod (&a, intgr, flg); /* sep int & frac */ vax_hmod (&a, intgr, flg); /* sep int & frac */
return h_rpackh (&a, hflt); /* round and pack frac */ return h_rpackh (&a, hflt); /* round and pack frac */
} }
@ -642,11 +663,14 @@ void vax_hadd (UFPH *a, UFPH *b)
int32 ediff; int32 ediff;
UFPH t; UFPH t;
if (a->exp == 0) { /* s1 = 0? */ if ((a->frac.f3 == 0) && (a->frac.f2 == 0) && /* s1 = 0? */
(a->frac.f1 == 0) && (a->frac.f0 == 0)) {
*a = *b; /* result is s2 */ *a = *b; /* result is s2 */
return; return;
} }
if (b->exp == 0) return; /* s2 = 0? */ if ((b->frac.f3 == 0) && (b->frac.f2 == 0) && /* s2 = 0? */
(b->frac.f1 == 0) && (b->frac.f0 == 0))
return;
if ((a->exp < b->exp) || /* |s1| < |s2|? */ if ((a->exp < b->exp) || /* |s1| < |s2|? */
((a->exp == b->exp) && (qp_cmp (&a->frac, &b->frac) < 0))) { ((a->exp == b->exp) && (qp_cmp (&a->frac, &b->frac) < 0))) {
t = *a; /* swap */ t = *a; /* swap */
@ -662,8 +686,7 @@ if (a->sign ^ b->sign) { /* eff sub? */
} }
else { else {
if (ediff) qp_rsh (&b->frac, ediff); /* add, denormalize */ if (ediff) qp_rsh (&b->frac, ediff); /* add, denormalize */
qp_add (&a->frac, &b->frac); /* add frac */ if (qp_add (&a->frac, &b->frac)) { /* add frac, carry? */
if (qp_cmp (&a->frac, &b->frac) < 0) { /* chk for carry */
qp_rsh (&a->frac, 1); /* renormalize */ qp_rsh (&a->frac, 1); /* renormalize */
a->frac.f3 = a->frac.f3 | UH_NM_H; /* add norm bit */ a->frac.f3 = a->frac.f3 | UH_NM_H; /* add norm bit */
a->exp = a->exp + 1; /* incr exp */ a->exp = a->exp + 1; /* incr exp */
@ -674,9 +697,9 @@ return;
/* Floating multiply - 128b * 128b */ /* Floating multiply - 128b * 128b */
void vax_hmul (UFPH *a, UFPH *b) void vax_hmul (UFPH *a, UFPH *b, uint32 mlo)
{ {
int32 i; int32 i, c;
UQP accum = { 0, 0, 0, 0 }; UQP accum = { 0, 0, 0, 0 };
if ((a->exp == 0) || (b->exp == 0)) { /* zero argument? */ if ((a->exp == 0) || (b->exp == 0)) { /* zero argument? */
@ -688,11 +711,14 @@ if ((a->exp == 0) || (b->exp == 0)) { /* zero argument? */
a->sign = a->sign ^ b->sign; /* sign of result */ a->sign = a->sign ^ b->sign; /* sign of result */
a->exp = a->exp + b->exp - H_BIAS; /* add exponents */ a->exp = a->exp + b->exp - H_BIAS; /* add exponents */
for (i = 0; i < 128; i++) { /* quad precision */ for (i = 0; i < 128; i++) { /* quad precision */
if (a->frac.f0 & 1) c = qp_add (&accum, &b->frac); /* mplr low? add */
else c = 0;
qp_rsh (&accum, 1); /* shift result */ qp_rsh (&accum, 1); /* shift result */
if (a->frac.f0 & 1) qp_add (&accum, &b->frac); /* mplr low? add */ if (c) accum.f3 = accum.f3 | UH_NM_H; /* add carry out */
qp_rsh (&a->frac, 1); /* shift mplr */ qp_rsh (&a->frac, 1); /* shift mplr */
} }
a->frac = accum; /* result */ a->frac = accum; /* result */
a->frac.f0 = a->frac.f0 & ~mlo; /* mask low frac */
h_normh (a); /* normalize */ h_normh (a); /* normalize */
return; return;
} }
@ -743,7 +769,7 @@ return;
void vax_hdiv (UFPH *a, UFPH *b) void vax_hdiv (UFPH *a, UFPH *b)
{ {
int32 i; int32 i;
UQP ndvr, quo = { 0, 0, 0, 0 }; UQP quo = { 0, 0, 0, 0 };
if (a->exp == 0) FLT_DZRO_FAULT; /* divr = 0? */ if (a->exp == 0) FLT_DZRO_FAULT; /* divr = 0? */
if (b->exp == 0) return; /* divd = 0? */ if (b->exp == 0) return; /* divd = 0? */
@ -751,12 +777,10 @@ b->sign = b->sign ^ a->sign; /* result sign */
b->exp = b->exp - a->exp + H_BIAS + 1; /* unbiased exp */ b->exp = b->exp - a->exp + H_BIAS + 1; /* unbiased exp */
qp_rsh (&a->frac, 1); /* allow 1 bit left */ qp_rsh (&a->frac, 1); /* allow 1 bit left */
qp_rsh (&b->frac, 1); qp_rsh (&b->frac, 1);
ndvr = a->frac; /* copy divisor */
qp_neg (&ndvr); /* and negate */
for (i = 0; i < 128; i++) { /* divide loop */ for (i = 0; i < 128; i++) { /* divide loop */
qp_lsh (&quo, 1); /* shift quo */ qp_lsh (&quo, 1); /* shift quo */
if (qp_cmp (&b->frac, &a->frac) >= 0) { /* div step ok? */ if (qp_cmp (&b->frac, &a->frac) >= 0) { /* div step ok? */
qp_add (&b->frac, &ndvr); /* "subtract" */ qp_sub (&b->frac, &a->frac); /* subtract */
quo.f0 = quo.f0 + 1; /* quo bit = 1 */ quo.f0 = quo.f0 + 1; /* quo bit = 1 */
} }
qp_lsh (&b->frac, 1); /* shift divd */ qp_lsh (&b->frac, 1); /* shift divd */
@ -781,33 +805,63 @@ if (a->f0 > b->f0) return +1;
return 0; /* all equal */ return 0; /* all equal */
} }
void qp_add (UQP *a, UQP *b) uint32 qp_add (UQP *a, UQP *b)
{ {
uint32 cry1, cry2, cry3, cry4;
a->f0 = (a->f0 + b->f0) & LMASK; /* add lo */ a->f0 = (a->f0 + b->f0) & LMASK; /* add lo */
if (a->f0 < b->f0) a->f1 = a->f1 + 1; /* carry? */ cry1 = (a->f0 < b->f0); /* carry? */
a->f1 = (a->f1 + b->f1) & LMASK; /* add mid2 */ a->f1 = (a->f1 + b->f1 + cry1) & LMASK; /* add mid2 */
if (a->f1 < b->f1) a->f2 = a->f2 + 1; /* carry? */ cry2 = (a->f1 < b->f1) || (cry1 && (a->f1 == b->f1)); /* carry? */
a->f2 = (a->f2 + b->f2) & LMASK; /* add mid1 */ a->f2 = (a->f2 + b->f2 + cry2) & LMASK; /* add mid1 */
if (a->f2 < b->f2) a->f3 = a->f3 + 1; /* carry? */ cry3 = (a->f2 < b->f2) || (cry2 && (a->f2 == b->f2)); /* carry? */
a->f3 = (a->f3 + b->f3) & LMASK; /* add hi */ a->f3 = (a->f3 + b->f3 + cry3) & LMASK; /* add hi */
return; cry4 = (a->f3 < b->f3) || (cry3 && (a->f3 == b->f3)); /* carry? */
return cry4; /* return carry out */
} }
void qp_inc (UQP *a) void qp_inc (UQP *a)
{ {
a->f0 = (a->f0 + 1) & LMASK; /* inc lo */ a->f0 = (a->f0 + 1) & LMASK; /* inc lo */
if (a->f0 == 0) a->f1 = (a->f1 + 1) & LMASK; /* propagate carry */ if (a->f0 == 0) { /* propagate carry */
if (a->f1 == 0) a->f2 = (a->f2 + 1) & LMASK; a->f1 = (a->f1 + 1) & LMASK;
if (a->f2 == 0) a->f3 = (a->f3 + 1) & LMASK; if (a->f1 == 0) {
a->f2 = (a->f2 + 1) & LMASK;
if (a->f2 == 0) {
a->f3 = (a->f3 + 1) & LMASK;
}
}
}
return; return;
} }
void qp_neg (UQP *r) uint32 qp_sub (UQP *a, UQP *b)
{ {
r->f0 = NEG (r->f0); /* neg lo */ uint32 brw1, brw2, brw3, brw4;
r->f1 = (~r->f1 + (r->f0 == 0)) & LMASK; /* complement rest */
r->f2 = (~r->f2 + (r->f1 == 0)) & LMASK; /* propagate carry */ brw1 = (a->f0 < b->f0); /* borrow? */
r->f3 = (~r->f3 + (r->f2 == 0)) & LMASK; a->f0 = (a->f0 - b->f0) & LMASK; /* sub lo */
brw2 = (a->f1 < b->f1) || (brw1 && (a->f1 == b->f1)); /* borrow? */
a->f1 = (a->f1 - b->f1 - brw1) & LMASK; /* sub mid1 */
brw3 = (a->f2 < b->f2) || (brw2 && (a->f2 == b->f2)); /* borrow? */
a->f2 = (a->f2 - b->f2 - brw2) & LMASK; /* sub mid2 */
brw4 = (a->f3 < b->f3) || (brw3 && (a->f3 == b->f3)); /* borrow? */
a->f3 = (a->f3 - b->f3 - brw3) & LMASK; /* sub high */
return brw4;
}
void qp_neg (UQP *a)
{
uint32 cryin;
cryin = 1;
a->f0 = (~a->f0 + cryin) & LMASK;
if (a->f0 != 0) cryin = 0;
a->f1 = (~a->f1 + cryin) & LMASK;
if (a->f1 != 0) cryin = 0;
a->f2 = (~a->f2 + cryin) & LMASK;
if (a->f2 != 0) cryin = 0;
a->f3 = (~a->f3 + cryin) & LMASK;
return; return;
} }
@ -985,7 +1039,7 @@ static UQP f_round = { 0, 0, 0, UH_FRND };
static UQP d_round = { 0, 0, UH_DRND, 0 }; static UQP d_round = { 0, 0, UH_DRND, 0 };
if (rh) *rh = 0; /* assume 0 */ if (rh) *rh = 0; /* assume 0 */
if (r->exp == 0) return 0; /* exp = 0? done */ if ((r->frac.f3 == 0) && (r->frac.f2 == 0)) return 0; /* frac = 0? done */
qp_add (&r->frac, rh? &d_round: &f_round); qp_add (&r->frac, rh? &d_round: &f_round);
if ((r->frac.f3 & UH_NM_H) == 0) { /* carry out? */ if ((r->frac.f3 & UH_NM_H) == 0) { /* carry out? */
qp_rsh (&r->frac, 1); /* renormalize */ qp_rsh (&r->frac, 1); /* renormalize */
@ -1007,7 +1061,7 @@ int32 h_rpackg (UFPH *r, int32 *rh)
static UQP g_round = { 0, 0, UH_GRND, 0 }; static UQP g_round = { 0, 0, UH_GRND, 0 };
*rh = 0; /* assume 0 */ *rh = 0; /* assume 0 */
if (r->exp == 0) return 0; /* exp = 0? done */ if ((r->frac.f3 == 0) && (r->frac.f2 == 0)) return 0; /* frac = 0? done */
qp_add (&r->frac, &g_round); /* round */ qp_add (&r->frac, &g_round); /* round */
if ((r->frac.f3 & UH_NM_H) == 0) { /* carry out? */ if ((r->frac.f3 & UH_NM_H) == 0) { /* carry out? */
qp_rsh (&r->frac, 1); /* renormalize */ qp_rsh (&r->frac, 1); /* renormalize */
@ -1029,9 +1083,9 @@ int32 h_rpackh (UFPH *r, int32 *hflt)
static UQP h_round = { UH_HRND, 0, 0, 0 }; static UQP h_round = { UH_HRND, 0, 0, 0 };
hflt[0] = hflt[1] = hflt[2] = hflt[3] = 0; /* assume 0 */ hflt[0] = hflt[1] = hflt[2] = hflt[3] = 0; /* assume 0 */
if (r->exp == 0) return 0; /* exp = 0? done */ if ((r->frac.f3 == 0) && (r->frac.f2 == 0) && /* frac = 0? done */
qp_add (&r->frac, &h_round); /* round */ (r->frac.f1 == 0) && (r->frac.f0 == 0)) return 0;
if ((r->frac.f3 & UH_NM_H) == 0) { /* carry out? */ if (qp_add (&r->frac, &h_round)) { /* round, carry out? */
qp_rsh (&r->frac, 1); /* renormalize */ qp_rsh (&r->frac, 1); /* renormalize */
r->exp = r->exp + 1; r->exp = r->exp + 1;
} }
@ -1085,7 +1139,8 @@ void h_write_q (int32 spec, int32 va, int32 vl, int32 vh, int32 acc)
int32 rn, mstat; int32 rn, mstat;
if (spec > (GRN | nPC)) { if (spec > (GRN | nPC)) {
if (Test (va + 7, WA, &mstat) >= 0) if ((Test (va + 7, WA, &mstat) >= 0) ||
(Test (va, WA, &mstat) < 0))
Write (va, vl, L_LONG, WA); Write (va, vl, L_LONG, WA);
Write (va + 4, vh, L_LONG, WA); Write (va + 4, vh, L_LONG, WA);
} }
@ -1103,7 +1158,8 @@ void h_write_o (int32 spec, int32 va, int32 *val, int32 acc)
int32 rn, mstat; int32 rn, mstat;
if (spec > (GRN | nPC)) { if (spec > (GRN | nPC)) {
if (Test (va + 15, WA, &mstat) >= 0) if ((Test (va + 15, WA, &mstat) >= 0) ||
(Test (va, WA, &mstat) < 0))
Write (va, val[0], L_LONG, WA); Write (va, val[0], L_LONG, WA);
Write (va + 4, val[1], L_LONG, WA); Write (va + 4, val[1], L_LONG, WA);
Write (va + 8, val[2], L_LONG, WA); Write (va + 8, val[2], L_LONG, WA);

View file

@ -1,6 +1,6 @@
/* vax_sys.c: VAX simulator interface /* vax_sys.c: VAX simulator interface
Copyright (c) 1998-2005, Robert M Supnik Copyright (c) 1998-2006, Robert M Supnik
Permission is hereby granted, free of charge, to any person obtaining a Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"), copy of this software and associated documentation files (the "Software"),
@ -23,6 +23,7 @@
used in advertising or otherwise to promote the sale, use or other dealings used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from Robert M Supnik. in this Software without prior written authorization from Robert M Supnik.
17-May-06 RMS Added CR11/CD11 support (from John Dundas)
01-Oct-2004 RMS Cloned from vax_sys.c 01-Oct-2004 RMS Cloned from vax_sys.c
*/ */
@ -37,6 +38,7 @@ extern DEVICE nvr_dev;
extern DEVICE sysd_dev; extern DEVICE sysd_dev;
extern DEVICE qba_dev; extern DEVICE qba_dev;
extern DEVICE tti_dev, tto_dev; extern DEVICE tti_dev, tto_dev;
extern DEVICE cr_dev;
extern DEVICE lpt_dev; extern DEVICE lpt_dev;
extern DEVICE clk_dev; extern DEVICE clk_dev;
extern DEVICE rq_dev, rqb_dev, rqc_dev, rqd_dev; extern DEVICE rq_dev, rqb_dev, rqc_dev, rqd_dev;
@ -68,6 +70,7 @@ DEVICE *sim_devices[] = {
&clk_dev, &clk_dev,
&dz_dev, &dz_dev,
&vh_dev, &vh_dev,
&cr_dev,
&lpt_dev, &lpt_dev,
&rl_dev, &rl_dev,
&rq_dev, &rq_dev,

View file

@ -1,6 +1,6 @@
/* vaxmod_defs.h: VAX model-specific definitions file /* vaxmod_defs.h: VAX model-specific definitions file
Copyright (c) 1998-2005, Robert M Supnik Copyright (c) 1998-2006, Robert M Supnik
Permission is hereby granted, free of charge, to any person obtaining a Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"), copy of this software and associated documentation files (the "Software"),
@ -23,6 +23,8 @@
used in advertising or otherwise to promote the sale, use or other dealings used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from Robert M Supnik. in this Software without prior written authorization from Robert M Supnik.
17-May-06 RMS Added CR11/CD11 support
10-May-06 RMS Added NOP'd reserved operand checking macros
05-Oct-05 RMS Added XU definitions for autoconfigure 05-Oct-05 RMS Added XU definitions for autoconfigure
15-Jun-05 RMS Added QDSS support 15-Jun-05 RMS Added QDSS support
12-Sep-04 RMS Removed map_address prototype 12-Sep-04 RMS Removed map_address prototype
@ -198,6 +200,15 @@
#define CQMAMASK (CQMSIZE - 1) /* Qmem addr mask */ #define CQMAMASK (CQMSIZE - 1) /* Qmem addr mask */
#define CQMBASE 0x30000000 /* Qmem base */ #define CQMBASE 0x30000000 /* Qmem base */
/* Machine specific reserved operand tests (all NOPs) */
#define ML_PA_TEST(r)
#define ML_LR_TEST(r)
#define ML_BR_TEST(r)
#define LP_AST_TEST(r)
#define LP_MBZ84_TEST(r)
#define LP_MBZ92_TEST(r)
/* Qbus I/O modes */ /* Qbus I/O modes */
#define READ 0 /* PDP-11 compatibility */ #define READ 0 /* PDP-11 compatibility */
@ -285,6 +296,8 @@ typedef struct {
#define IOLN_XU 010 #define IOLN_XU 010
#define IOBA_RP (IOPAGEBASE + 016700) /* RP/RM */ #define IOBA_RP (IOPAGEBASE + 016700) /* RP/RM */
#define IOLN_RP 054 #define IOLN_RP 054
#define IOBA_CR (IOPAGEBASE + 017160) /* CD/CR/CM */
#define IOLN_CR 010
#define IOBA_RX (IOPAGEBASE + 017170) /* RXV11 */ #define IOBA_RX (IOPAGEBASE + 017170) /* RXV11 */
#define IOLN_RX 004 #define IOLN_RX 004
#define IOBA_RY (IOPAGEBASE + 017170) /* RXV21 */ #define IOBA_RY (IOPAGEBASE + 017170) /* RXV21 */
@ -336,6 +349,7 @@ typedef struct {
#define INT_V_VHRX 9 /* DHQ11 */ #define INT_V_VHRX 9 /* DHQ11 */
#define INT_V_VHTX 10 #define INT_V_VHTX 10
#define INT_V_QDSS 11 /* QDSS */ #define INT_V_QDSS 11 /* QDSS */
#define INT_V_CR 12
#define INT_CLK (1u << INT_V_CLK) #define INT_CLK (1u << INT_V_CLK)
#define INT_RQ (1u << INT_V_RQ) #define INT_RQ (1u << INT_V_RQ)
@ -359,6 +373,7 @@ typedef struct {
#define INT_VHRX (1u << INT_V_VHRX) #define INT_VHRX (1u << INT_V_VHRX)
#define INT_VHTX (1u << INT_V_VHTX) #define INT_VHTX (1u << INT_V_VHTX)
#define INT_QDSS (1u << INT_V_QDSS) #define INT_QDSS (1u << INT_V_QDSS)
#define INT_CR (1u << INT_V_CR)
#define IPL_CLK (0x16 - IPL_HMIN) /* relative IPL */ #define IPL_CLK (0x16 - IPL_HMIN) /* relative IPL */
#define IPL_RQ (0x15 - IPL_HMIN) #define IPL_RQ (0x15 - IPL_HMIN)
@ -382,6 +397,7 @@ typedef struct {
#define IPL_VHRX (0x14 - IPL_HMIN) #define IPL_VHRX (0x14 - IPL_HMIN)
#define IPL_VHTX (0x14 - IPL_HMIN) #define IPL_VHTX (0x14 - IPL_HMIN)
#define IPL_QDSS (0x14 - IPL_HMIN) #define IPL_QDSS (0x14 - IPL_HMIN)
#define IPL_CR (0x14 - IPL_HMIN)
#define IPL_HMAX 0x17 /* highest hwre level */ #define IPL_HMAX 0x17 /* highest hwre level */
#define IPL_HMIN 0x14 /* lowest hwre level */ #define IPL_HMIN 0x14 /* lowest hwre level */
@ -399,6 +415,7 @@ typedef struct {
#define VEC_RL (VEC_Q + 0160) #define VEC_RL (VEC_Q + 0160)
#define VEC_LPT (VEC_Q + 0200) #define VEC_LPT (VEC_Q + 0200)
#define VEC_TS (VEC_Q + 0224) #define VEC_TS (VEC_Q + 0224)
#define VEC_CR (VEC_Q + 0230)
#define VEC_RP (VEC_Q + 0254) #define VEC_RP (VEC_Q + 0254)
#define VEC_TQ (VEC_Q + 0260) #define VEC_TQ (VEC_Q + 0260)
#define VEC_RX (VEC_Q + 0264) #define VEC_RX (VEC_Q + 0264)

File diff suppressed because it is too large Load diff

View file

@ -82,7 +82,8 @@ PDP11 = ${PDP11D}pdp11_fp.c ${PDP11D}pdp11_cpu.c ${PDP11D}pdp11_dz.c \
${PDP11D}pdp11_rq.c ${PDP11D}pdp11_tq.c ${PDP11D}pdp11_pclk.c \ ${PDP11D}pdp11_rq.c ${PDP11D}pdp11_tq.c ${PDP11D}pdp11_pclk.c \
${PDP11D}pdp11_ry.c ${PDP11D}pdp11_pt.c ${PDP11D}pdp11_hk.c \ ${PDP11D}pdp11_ry.c ${PDP11D}pdp11_pt.c ${PDP11D}pdp11_hk.c \
${PDP11D}pdp11_xq.c ${PDP11D}pdp11_xu.c ${PDP11D}pdp11_vh.c \ ${PDP11D}pdp11_xq.c ${PDP11D}pdp11_xu.c ${PDP11D}pdp11_vh.c \
${PDP11D}pdp11_rh.c ${PDP11D}pdp11_tu.c ${PDP11D}pdp11_cpumod.c ${PDP11D}pdp11_rh.c ${PDP11D}pdp11_tu.c ${PDP11D}pdp11_cpumod.c \
${PDP11D}pdp11_cr.c
PDP11_OPT = -DVM_PDP11 -I ${PDP11D} ${NETWORK_OPT} PDP11_OPT = -DVM_PDP11 -I ${PDP11D} ${NETWORK_OPT}
@ -95,19 +96,20 @@ VAX = ${VAXD}vax_cpu.c ${VAXD}vax_cpu1.c ${VAXD}vax_fpa.c ${VAXD}vax_io.c \
${PDP11D}pdp11_rl.c ${PDP11D}pdp11_rq.c ${PDP11D}pdp11_ts.c \ ${PDP11D}pdp11_rl.c ${PDP11D}pdp11_rq.c ${PDP11D}pdp11_ts.c \
${PDP11D}pdp11_dz.c ${PDP11D}pdp11_lp.c ${PDP11D}pdp11_tq.c \ ${PDP11D}pdp11_dz.c ${PDP11D}pdp11_lp.c ${PDP11D}pdp11_tq.c \
${PDP11D}pdp11_xq.c ${PDP11D}pdp11_ry.c \ ${PDP11D}pdp11_xq.c ${PDP11D}pdp11_ry.c \
${PDP11D}pdp11_vh.c ${PDP11D}pdp11_vh.c ${PDP11D}pdp11_cr.c
VAX_OPT = -DVM_VAX -DUSE_INT64 -DUSE_ADDR64 -I ${VAXD} -I ${PDP11D} ${NETWORK_OPT} VAX_OPT = -DVM_VAX -DUSE_INT64 -DUSE_ADDR64 -I ${VAXD} -I ${PDP11D} ${NETWORK_OPT}
VAX780 = ${VAXD}vax_cpu.c ${VAXD}vax_cpu1.c ${VAXD}vax_fpa.c \ VAX780 = ${VAXD}vax_cpu.c ${VAXD}vax_cpu1.c ${VAXD}vax_fpa.c \
${VAXD}vax_cis.c ${VAXD}vax_octa.c ${VAXD}vax_cmode.c \ ${VAXD}vax_cis.c ${VAXD}vax_octa.c ${VAXD}vax_cmode.c \
${VAXD}vax_mmu.c ${VAXD}vax780_stddev.c ${VAXD}vax780_sbi.c \ ${VAXD}vax_mmu.c ${VAXD}vax_sys.c ${VAXD}vax_syscm.c \
${VAXD}vax780_stddev.c ${VAXD}vax780_sbi.c \
${VAXD}vax780_mem.c ${VAXD}vax780_uba.c ${VAXD}vax780_mba.c \ ${VAXD}vax780_mem.c ${VAXD}vax780_uba.c ${VAXD}vax780_mba.c \
${VAXD}vax_sys.c ${VAXD}vax_syscm.c ${VAXD}vax780_syslist.c \ ${VAXD}vax780_fload.c ${VAXD}vax780_syslist.c \
${PDP11D}pdp11_rl.c ${PDP11D}pdp11_rq.c ${PDP11D}pdp11_ts.c \ ${PDP11D}pdp11_rl.c ${PDP11D}pdp11_rq.c ${PDP11D}pdp11_ts.c \
${PDP11D}pdp11_dz.c ${PDP11D}pdp11_lp.c ${PDP11D}pdp11_tq.c \ ${PDP11D}pdp11_dz.c ${PDP11D}pdp11_lp.c ${PDP11D}pdp11_tq.c \
${PDP11D}pdp11_xu.c ${PDP11D}pdp11_ry.c \ ${PDP11D}pdp11_xu.c ${PDP11D}pdp11_ry.c ${PDP11D}pdp11_cr.c \
${PDP11D}pdp11_rp.c ${PDP11D}pdp11_tu.c ${PDP11D}pdp11_hk.c ${PDP11D}pdp11_rp.c ${PDP11D}pdp11_tu.c ${PDP11D}pdp11_hk.c
VAX780_OPT = -DVM_VAX -DVAX_780 -DUSE_INT64 -DUSE_ADDR64 -I ${VAXD} -I ${PDP11D} ${NETWORK_OPT} VAX780_OPT = -DVM_VAX -DVAX_780 -DUSE_INT64 -DUSE_ADDR64 -I ${VAXD} -I ${PDP11D} ${NETWORK_OPT}
@ -169,6 +171,15 @@ I1620_OPT = -I ${I1620D}
I7094D = I7094/
I7094 = ${I7094D}i7094_cpu.c ${I7094D}i7094_cpu1.c ${I7094D}i7094_io.c \
${I7094D}i7094_cd.c ${I7094D}i7094_clk.c ${I7094D}i7094_com.c \
${I7094D}i7094_drm.c ${I7094D}i7094_dsk.c ${I7094D}i7094_sys.c \
${I7094D}i7094_lp.c ${I7094D}i7094_mt.c
I7094_OPT = -DUSE_INT64 -I ${I7094D}
IBM1130D = Ibm1130/ IBM1130D = Ibm1130/
IBM1130 = ${IBM1130D}ibm1130_cpu.c ${IBM1130D}ibm1130_cr.c \ IBM1130 = ${IBM1130D}ibm1130_cpu.c ${IBM1130D}ibm1130_cr.c \
${IBM1130D}ibm1130_disk.c ${IBM1130D}ibm1130_stddev.c \ ${IBM1130D}ibm1130_disk.c ${IBM1130D}ibm1130_stddev.c \
@ -247,7 +258,7 @@ ALL = ${BIN}pdp1${EXE} ${BIN}pdp4${EXE} ${BIN}pdp7${EXE} ${BIN}pdp8${EXE} \
${BIN}vax${EXE} ${BIN}vax780${EXE} ${BIN}nova${EXE} ${BIN}eclipse${EXE} \ ${BIN}vax${EXE} ${BIN}vax780${EXE} ${BIN}nova${EXE} ${BIN}eclipse${EXE} \
${BIN}hp2100${EXE} ${BIN}i1401${EXE} ${BIN}i1620${EXE} ${BIN}s3${EXE} \ ${BIN}hp2100${EXE} ${BIN}i1401${EXE} ${BIN}i1620${EXE} ${BIN}s3${EXE} \
${BIN}altair${EXE} ${BIN}altairz80${EXE} ${BIN}gri${EXE} \ ${BIN}altair${EXE} ${BIN}altairz80${EXE} ${BIN}gri${EXE} \
${BIN}i1620${EXE} ${BIN}ibm1130${EXE} ${BIN}id16${EXE} \ ${BIN}i1620${EXE} ${BIN}i7094${EXE} ${BIN}ibm1130${EXE} ${BIN}id16${EXE} \
${BIN}id32${EXE} ${BIN}sds${EXE} ${BIN}lgp${EXE} ${BIN}h316${EXE} ${BIN}id32${EXE} ${BIN}sds${EXE} ${BIN}lgp${EXE} ${BIN}h316${EXE}
all : ${ALL} all : ${ALL}
@ -338,6 +349,11 @@ ${BIN}i1620${EXE} : ${I1620} ${SIM}
${CC} ${I1620} ${SIM} ${I1620_OPT} -o $@ ${LDFLAGS} ${CC} ${I1620} ${SIM} ${I1620_OPT} -o $@ ${LDFLAGS}
${BIN}i7094${EXE} : ${I7094} ${SIM}
${CC} ${I7094} ${SIM} ${I7094_OPT} -o $@ ${LDFLAGS}
${BIN}ibm1130${EXE} : ${IBM1130} ${BIN}ibm1130${EXE} : ${IBM1130}
${CC} ${IBM1130} ${SIM} ${IBM1130_OPT} -o $@ ${LDFLAGS} ${CC} ${IBM1130} ${SIM} ${IBM1130_OPT} -o $@ ${LDFLAGS}

176
scp.c
View file

@ -23,6 +23,7 @@
used in advertising or otherwise to promote the sale, use or other dealings used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from Robert M Supnik. in this Software without prior written authorization from Robert M Supnik.
14-Feb-06 RMS Upgraded save file format to V3.5
18-Jan-06 RMS Added fprint_stopped_gen 18-Jan-06 RMS Added fprint_stopped_gen
Added breakpoint spaces Added breakpoint spaces
Fixed unaligned register access (found by Doug Carman) Fixed unaligned register access (found by Doug Carman)
@ -317,6 +318,7 @@ t_stat attach_err (UNIT *uptr, t_stat stat);
t_stat detach_all (int32 start_device, t_bool shutdown); t_stat detach_all (int32 start_device, t_bool shutdown);
t_stat assign_device (DEVICE *dptr, char *cptr); t_stat assign_device (DEVICE *dptr, char *cptr);
t_stat deassign_device (DEVICE *dptr); t_stat deassign_device (DEVICE *dptr);
t_stat run_boot_prep (void);
t_stat exdep_reg_loop (FILE *ofile, SCHTAB *schptr, int32 flag, char *cptr, t_stat exdep_reg_loop (FILE *ofile, SCHTAB *schptr, int32 flag, char *cptr,
REG *lowr, REG *highr, uint32 lows, uint32 highs); REG *lowr, REG *highr, uint32 lows, uint32 highs);
t_stat ex_reg (FILE *ofile, t_value val, int32 flag, REG *rptr, uint32 idx); t_stat ex_reg (FILE *ofile, t_value val, int32 flag, REG *rptr, uint32 idx);
@ -363,12 +365,27 @@ FILE *sim_deb = NULL; /* debug file */
static SCHTAB sim_stab; static SCHTAB sim_stab;
static UNIT sim_step_unit = { UDATA (&step_svc, 0, 0) }; static UNIT sim_step_unit = { UDATA (&step_svc, 0, 0) };
#if defined USE_INT64
static const char *sim_si64 = "64b data";
#else
static const char *sim_si64 = "32b data";
#endif
#if defined USE_ADDR64
static const char *sim_sa64 = "64b addresses";
#else
static const char *sim_sa64 = "32b addresses";
#endif
#if defined USE_NETWORK
static const char *sim_snet = "Ethernet support";
#else
static const char *sim_snet = "no Ethernet";
#endif
/* Tables and strings */ /* Tables and strings */
const char save_vercur[] = "V3.2"; const char save_vercur[] = "V3.5";
const char save_ver32[] = "V3.2";
const char save_ver30[] = "V3.0"; const char save_ver30[] = "V3.0";
const char save_ver210[] = "V2.10";
const char *scp_error_messages[] = { const char *scp_error_messages[] = {
"Address space exceeded", "Address space exceeded",
"Unit not attached", "Unit not attached",
@ -1282,25 +1299,10 @@ return;
t_stat show_version (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, char *cptr) t_stat show_version (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, char *cptr)
{ {
int32 vmaj = SIM_MAJOR, vmin = SIM_MINOR, vpat = SIM_PATCH; int32 vmaj = SIM_MAJOR, vmin = SIM_MINOR, vpat = SIM_PATCH;
#if defined USE_INT64
static const char *si64 = "64b data";
#else
static const char *si64 = "32b data";
#endif
#if defined USE_ADDR64
static const char *sa64 = "64b addresses";
#else
static const char *sa64 = "32b addresses";
#endif
#if defined USE_NETWORK
static const char *snet = "Ethernet support";
#else
static const char *snet = "no Ethernet";
#endif
if (cptr && (*cptr != 0)) return SCPE_2MARG; if (cptr && (*cptr != 0)) return SCPE_2MARG;
fprintf (st, "%s simulator V%d.%d-%d", sim_name, vmaj, vmin, vpat); fprintf (st, "%s simulator V%d.%d-%d", sim_name, vmaj, vmin, vpat);
if (flag) fprintf (st, " [%s, %s, %s]", si64, sa64, snet); if (flag) fprintf (st, " [%s, %s, %s]", sim_si64, sim_sa64, sim_snet);
fprintf (st, "\n"); fprintf (st, "\n");
return SCPE_OK; return SCPE_OK;
} }
@ -1950,11 +1952,11 @@ REG *rptr;
#define WRITE_I(xx) sim_fwrite (&(xx), sizeof (xx), 1, sfile) #define WRITE_I(xx) sim_fwrite (&(xx), sizeof (xx), 1, sfile)
fputs (save_vercur, sfile); /* [V2.5] save format */ fprintf (sfile, "%s\n%s\n%s\n%s\n%s\n%.0f\n",
fputc ('\n', sfile); save_vercur, /* [V2.5] save format */
fputs (sim_name, sfile); /* sim name */ sim_name, /* sim name */
fputc ('\n', sfile); sim_si64, sim_sa64, sim_snet, /* [V3.5] options */
fprintf (sfile, "%.0f\n", sim_time); /* [V3.2] sim time */ sim_time); /* [V3.2] sim time */
WRITE_I (sim_rtime); /* [V2.6] sim rel time */ WRITE_I (sim_rtime); /* [V2.6] sim rel time */
for (i = 0; (dptr = sim_devices[i]) != NULL; i++) { /* loop thru devices */ for (i = 0; (dptr = sim_devices[i]) != NULL; i++) { /* loop thru devices */
@ -1973,6 +1975,7 @@ for (i = 0; (dptr = sim_devices[i]) != NULL; i++) { /* loop thru devices */
WRITE_I (uptr->u5); /* [V3.0] more unit */ WRITE_I (uptr->u5); /* [V3.0] more unit */
WRITE_I (uptr->u6); WRITE_I (uptr->u6);
WRITE_I (uptr->flags); /* [V2.10] flags */ WRITE_I (uptr->flags); /* [V2.10] flags */
WRITE_I (uptr->capac); /* [V3.5] capacity */
if (uptr->flags & UNIT_ATT) fputs (uptr->filename, sfile); if (uptr->flags & UNIT_ATT) fputs (uptr->filename, sfile);
fputc ('\n', sfile); fputc ('\n', sfile);
if (((uptr->flags & (UNIT_FIX + UNIT_ATTABLE)) == UNIT_FIX) && if (((uptr->flags & (UNIT_FIX + UNIT_ATTABLE)) == UNIT_FIX) &&
@ -2052,11 +2055,11 @@ char buf[CBUFSIZE];
void *mbuf; void *mbuf;
int32 j, blkcnt, limit, unitno, time, flg; int32 j, blkcnt, limit, unitno, time, flg;
uint32 us, depth; uint32 us, depth;
t_addr k, high; t_addr k, high, old_capac;
t_value val, mask; t_value val, mask;
t_stat r; t_stat r;
size_t sz; size_t sz;
t_bool v32 = FALSE, v30 = FALSE; t_bool v35, v32;
DEVICE *dptr; DEVICE *dptr;
UNIT *uptr; UNIT *uptr;
REG *rptr; REG *rptr;
@ -2067,10 +2070,11 @@ REG *rptr;
return SCPE_IOERR; return SCPE_IOERR;
READ_S (buf); /* [V2.5+] read version */ READ_S (buf); /* [V2.5+] read version */
if (strcmp (buf, save_vercur) == 0) v32 = v30 = TRUE; /* version 3.2? */ v35 = v32 = FALSE;
else if (strcmp (buf, save_ver30) == 0) v30 = TRUE; /* version 3.0? */ if (strcmp (buf, save_vercur) == 0) v35 = v32 = TRUE; /* version 3.5? */
else if (strcmp (buf, save_ver210) != 0) { /* version 2.10? */ else if (strcmp (buf, save_ver32) == 0) v32 = TRUE; /* version 3.2? */
printf ("Invalid file version: %s\n", buf); /* no, unknown */ else if (strcmp (buf, save_ver30) != 0) { /* version 3.0? */
printf ("Invalid file version: %s\n", buf);
return SCPE_INCOMP; return SCPE_INCOMP;
} }
READ_S (buf); /* read sim name */ READ_S (buf); /* read sim name */
@ -2078,7 +2082,20 @@ if (strcmp (buf, sim_name)) { /* name match? */
printf ("Wrong system type: %s\n", buf); printf ("Wrong system type: %s\n", buf);
return SCPE_INCOMP; return SCPE_INCOMP;
} }
if (v32) { /* [V3.2] time as string */ if (v35) { /* [V3.5+] options */
READ_S (buf); /* integer size */
if (strcmp (buf, sim_si64) != 0) {
printf ("Incompatible integer size, save file = %s\n", buf);
return SCPE_INCOMP;
}
READ_S (buf); /* address size */
if (strcmp (buf, sim_sa64) != 0) {
printf ("Incompatible address size, save file = %s\n", buf);
return SCPE_INCOMP;
}
READ_S (buf); /* Ethernet */
}
if (v32) { /* [V3.2+] time as string */
READ_S (buf); READ_S (buf);
sscanf (buf, "%lf", &sim_time); sscanf (buf, "%lf", &sim_time);
} }
@ -2092,15 +2109,13 @@ for ( ;; ) { /* device loop */
printf ("Invalid device name: %s\n", buf); printf ("Invalid device name: %s\n", buf);
return SCPE_INCOMP; return SCPE_INCOMP;
} }
if (v30) { /* [V3.0+] */ READ_S (buf); /* [V3.0+] logical name */
READ_S (buf); /* read logical name */ deassign_device (dptr); /* delete old name */
deassign_device (dptr); /* delete old name */ if ((buf[0] != 0) &&
if ((buf[0] != 0) && ((r = assign_device (dptr, buf)) != SCPE_OK)) return r;
((r = assign_device (dptr, buf)) != SCPE_OK)) return r;
}
READ_I (flg); /* [V2.10+] ctlr flags */ READ_I (flg); /* [V2.10+] ctlr flags */
if (!v32) flg = ((flg & DEV_UFMASK_31) << (DEV_V_UF - DEV_V_UF_31)) | if (!v32) flg = ((flg & DEV_UFMASK_31) << (DEV_V_UF - DEV_V_UF_31)) |
(flg & ~DEV_UFMASK_31); /* [V3.2] flags moved */ (flg & ~DEV_UFMASK_31); /* [V3.2+] flags moved */
dptr->flags = (dptr->flags & ~DEV_RFLAGS) | /* restore ctlr flags */ dptr->flags = (dptr->flags & ~DEV_RFLAGS) | /* restore ctlr flags */
(flg & DEV_RFLAGS); (flg & DEV_RFLAGS);
for ( ;; ) { /* unit loop */ for ( ;; ) { /* unit loop */
@ -2116,13 +2131,15 @@ for ( ;; ) { /* device loop */
if (time > 0) sim_activate (uptr, time - 1); if (time > 0) sim_activate (uptr, time - 1);
READ_I (uptr->u3); /* device specific */ READ_I (uptr->u3); /* device specific */
READ_I (uptr->u4); READ_I (uptr->u4);
if (v30) { /* [V3.0+] */ READ_I (uptr->u5); /* [V3.0+] more dev spec */
READ_I (uptr->u5); /* more dev specific */ READ_I (uptr->u6);
READ_I (uptr->u6);
}
READ_I (flg); /* [V2.10+] unit flags */ READ_I (flg); /* [V2.10+] unit flags */
old_capac = uptr->capac; /* save current capacity */
if (v35) { /* [V3.5+] capacity */
READ_I (uptr->capac);
}
if (!v32) flg = ((flg & UNIT_UFMASK_31) << (UNIT_V_UF - UNIT_V_UF_31)) | if (!v32) flg = ((flg & UNIT_UFMASK_31) << (UNIT_V_UF - UNIT_V_UF_31)) |
(flg & ~UNIT_UFMASK_31); /* [V3.2] flags moved */ (flg & ~UNIT_UFMASK_31); /* [V3.2+] flags moved */
uptr->flags = (uptr->flags & ~UNIT_RFLAGS) | uptr->flags = (uptr->flags & ~UNIT_RFLAGS) |
(flg & UNIT_RFLAGS); /* restore */ (flg & UNIT_RFLAGS); /* restore */
READ_S (buf); /* attached file */ READ_S (buf); /* attached file */
@ -2148,12 +2165,13 @@ for ( ;; ) { /* device loop */
printf ("Can't restore memory: %s%d\n", sim_dname (dptr), unitno); printf ("Can't restore memory: %s%d\n", sim_dname (dptr), unitno);
return SCPE_INCOMP; return SCPE_INCOMP;
} }
if (high != uptr->capac) { if (high != old_capac) {
if ((dptr->flags & DEV_DYNM) && if ((dptr->flags & DEV_DYNM) &&
((dptr->msize == NULL) || ((dptr->msize == NULL) ||
(dptr->msize (uptr, (int32) high, NULL, NULL) != SCPE_OK))) { (dptr->msize (uptr, (int32) high, NULL, NULL) != SCPE_OK))) {
printf ("Can't change memory size: %s%d\n", printf ("Can't change memory size: %s%d\n",
sim_dname (dptr), unitno); sim_dname (dptr), unitno);
uptr->capac = old_capac;
return SCPE_INCOMP; return SCPE_INCOMP;
} }
uptr->capac = high; uptr->capac = high;
@ -2228,50 +2246,53 @@ void int_handler (int signal);
GET_SWITCHES (cptr); /* get switches */ GET_SWITCHES (cptr); /* get switches */
sim_step = 0; sim_step = 0;
if (((flag == RU_RUN) || (flag == RU_GO)) && (*cptr != 0)) { /* run or go */ if ((flag == RU_RUN) || (flag == RU_GO)) { /* run or go */
cptr = get_glyph (cptr, gbuf, 0); /* get next glyph */ if (*cptr != 0) { /* argument? */
if (sim_vm_parse_addr) /* address parser? */ cptr = get_glyph (cptr, gbuf, 0); /* get next glyph */
pcv = sim_vm_parse_addr (sim_dflt_dev, gbuf, &tptr); if (*cptr != 0) return SCPE_2MARG; /* should be end */
else pcv = strtotv (gbuf, &tptr, sim_PC->radix); if (sim_vm_parse_addr) /* address parser? */
if ((tptr == gbuf) || (*tptr != 0) || pcv = sim_vm_parse_addr (sim_dflt_dev, gbuf, &tptr);
(pcv > width_mask[sim_PC->width])) return SCPE_ARG; else pcv = strtotv (gbuf, &tptr, sim_PC->radix);/* parse PC */
put_rval (sim_PC, 0, pcv); if ((tptr == gbuf) || (*tptr != 0) || /* error? */
} (pcv > width_mask[sim_PC->width])) return SCPE_ARG;
put_rval (sim_PC, 0, pcv);
if (flag == RU_STEP) { /* step */
if (*cptr == 0) sim_step = 1;
else {
cptr = get_glyph (cptr, gbuf, 0);
sim_step = (int32) get_uint (gbuf, 10, INT_MAX, &r);
if ((r != SCPE_OK) || (sim_step <= 0)) return SCPE_ARG;
} }
if ((flag == RU_RUN) && /* run? */
((r = run_boot_prep ()) != SCPE_OK)) return r; /* reset sim */
} }
if (flag == RU_BOOT) { /* boot */ else if (flag == RU_STEP) { /* step */
if (*cptr != 0) { /* argument? */
cptr = get_glyph (cptr, gbuf, 0); /* get next glyph */
if (*cptr != 0) return SCPE_2MARG; /* should be end */
sim_step = (int32) get_uint (gbuf, 10, INT_MAX, &r);
if ((r != SCPE_OK) || (sim_step <= 0)) /* error? */
return SCPE_ARG;
}
else sim_step = 1;
}
else if (flag == RU_BOOT) { /* boot */
if (*cptr == 0) return SCPE_2FARG; /* must be more */ if (*cptr == 0) return SCPE_2FARG; /* must be more */
cptr = get_glyph (cptr, gbuf, 0); /* get next glyph */ cptr = get_glyph (cptr, gbuf, 0); /* get next glyph */
if (*cptr != 0) return SCPE_2MARG; /* should be end */
dptr = find_unit (gbuf, &uptr); /* locate unit */ dptr = find_unit (gbuf, &uptr); /* locate unit */
if (dptr == NULL) return SCPE_NXDEV; /* found dev? */ if (dptr == NULL) return SCPE_NXDEV; /* found dev? */
if (uptr == NULL) return SCPE_NXUN; /* valid unit? */ if (uptr == NULL) return SCPE_NXUN; /* valid unit? */
if (dptr->boot == NULL) return SCPE_NOFNC; /* can it boot? */ if (dptr->boot == NULL) return SCPE_NOFNC; /* can it boot? */
if (uptr->flags & UNIT_DIS) return SCPE_UDIS; /* disabled? */ if (uptr->flags & UNIT_DIS) return SCPE_UDIS; /* disabled? */
if ((uptr->flags & UNIT_ATTABLE) && if ((uptr->flags & UNIT_ATTABLE) && /* if attable, att? */
!(uptr->flags & UNIT_ATT)) return SCPE_UNATT; !(uptr->flags & UNIT_ATT)) return SCPE_UNATT;
unitno = (int32) (uptr - dptr->units); /* recover unit# */ unitno = (int32) (uptr - dptr->units); /* recover unit# */
if ((r = dptr->boot (unitno, dptr)) != SCPE_OK) return r; if ((r = run_boot_prep ()) != SCPE_OK) return r; /* reset sim */
if ((r = dptr->boot (unitno, dptr)) != SCPE_OK) /* boot device */
return r;
} }
if (*cptr != 0) return SCPE_2MARG; /* now eol? */ else if (flag != RU_CONT) return SCPE_IERR; /* must be cont */
if ((flag == RU_RUN) || (flag == RU_BOOT)) { /* run or boot */ for (i = 1; (dptr = sim_devices[i]) != NULL; i++) { /* reposition all */
sim_interval = 0; /* reset queue */ for (j = 0; j < dptr->numunits; j++) { /* seq devices */
sim_time = sim_rtime = 0;
noqueue_time = 0;
sim_clock_queue = NULL;
if ((r = reset_all_p (0)) != SCPE_OK) return r;
}
for (i = 1; (dptr = sim_devices[i]) != NULL; i++) {
for (j = 0; j < dptr->numunits; j++) {
uptr = dptr->units + j; uptr = dptr->units + j;
if ((uptr->flags & (UNIT_ATT + UNIT_SEQ)) == if ((uptr->flags & (UNIT_ATT + UNIT_SEQ)) ==
(UNIT_ATT + UNIT_SEQ)) (UNIT_ATT + UNIT_SEQ))
@ -2326,6 +2347,17 @@ if (sim_log) fprint_stopped (sim_log, r); /* log if enabled */
return SCPE_OK; return SCPE_OK;
} }
/* Common setup for RUN or BOOT */
t_stat run_boot_prep (void)
{
sim_interval = 0; /* reset queue */
sim_time = sim_rtime = 0;
noqueue_time = 0;
sim_clock_queue = NULL;
return reset_all_p (0);
}
/* Print stopped message */ /* Print stopped message */
void fprint_stopped_gen (FILE *st, t_stat v, REG *pc, DEVICE *dptr) void fprint_stopped_gen (FILE *st, t_stat v, REG *pc, DEVICE *dptr)

View file

@ -1,6 +1,6 @@
/* sim_fio.c: simulator file I/O library /* sim_fio.c: simulator file I/O library
Copyright (c) 1993-2005, Robert M Supnik Copyright (c) 1993-2006, Robert M Supnik
Permission is hereby granted, free of charge, to any person obtaining a Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"), copy of this software and associated documentation files (the "Software"),
@ -23,6 +23,8 @@
used in advertising or otherwise to promote the sale, use or other dealings used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from Robert M Supnik. in this Software without prior written authorization from Robert M Supnik.
15-May-06 RMS Added sim_fsize_name
21-Apr-06 RMS Added FreeBSD large file support (from Mark Martinec)
19-Nov-05 RMS Added OS/X large file support (from Peter Schorn) 19-Nov-05 RMS Added OS/X large file support (from Peter Schorn)
16-Aug-05 RMS Fixed C++ declaration and cast problems 16-Aug-05 RMS Fixed C++ declaration and cast problems
17-Jul-04 RMS Fixed bug in optimized sim_fread (reported by Scott Bailey) 17-Jul-04 RMS Fixed bug in optimized sim_fread (reported by Scott Bailey)
@ -126,6 +128,17 @@ return total;
/* Get file size */ /* Get file size */
uint32 sim_fsize_name (char *fname)
{
FILE *fp;
uint32 sz;
if ((fp = sim_fopen (fname, "rb")) == NULL) return 0;
sz = sim_fsize (fp);
fclose (fp);
return sz;
}
uint32 sim_fsize (FILE *fp) uint32 sim_fsize (FILE *fp)
{ {
uint32 pos, sz; uint32 pos, sz;
@ -279,7 +292,7 @@ return fseeko64 (st, xpos, origin);
/* Apple OS/X */ /* Apple OS/X */
#if defined (__APPLE__) #if defined (__APPLE__) || defined (__FreeBSD__)
#define _SIM_IO_FSEEK_EXT_ 1 #define _SIM_IO_FSEEK_EXT_ 1
int sim_fseek (FILE *st, t_addr xpos, int origin) int sim_fseek (FILE *st, t_addr xpos, int origin)

View file

@ -1,6 +1,6 @@
/* sim_fio.h: simulator file I/O library headers /* sim_fio.h: simulator file I/O library headers
Copyright (c) 1993-2005, Robert M Supnik Copyright (c) 1993-2006, Robert M Supnik
Permission is hereby granted, free of charge, to any person obtaining a Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"), copy of this software and associated documentation files (the "Software"),
@ -23,6 +23,7 @@
be used in advertising or otherwise to promote the sale, use or other dealings 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. in this Software without prior written authorization from Robert M Supnik.
15-May-06 RMS Added sim_fsize_name
16-Aug-05 RMS Fixed C++ declaration and cast problems 16-Aug-05 RMS Fixed C++ declaration and cast problems
02-Jan-04 RMS Split out from SCP 02-Jan-04 RMS Split out from SCP
*/ */
@ -40,5 +41,6 @@ int sim_fseek (FILE *st, t_addr offset, int whence);
size_t sim_fread (void *bptr, size_t size, size_t count, FILE *fptr); size_t sim_fread (void *bptr, size_t size, size_t count, FILE *fptr);
size_t sim_fwrite (void *bptr, size_t size, size_t count, FILE *fptr); size_t sim_fwrite (void *bptr, size_t size, size_t count, FILE *fptr);
uint32 sim_fsize (FILE *fptr); uint32 sim_fsize (FILE *fptr);
uint32 sim_fsize_name (char *fname);
#endif #endif

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