Notes For V3.4-0

The memory layout for the Interdata simulators has been changed.
Do not use Interdata SAVE files from prior revisions with V3.4.

1. New Features in 3.4

1.1 SCP and Libraries

- Revised interpretation of fprint_sym, fparse_sym returns
- Revised syntax for SET DEBUG
- DO command nesting allowed to ten levels

1.2 Interdata

- Revised memory model to be 16b instead of 8b

1.3 HP2100

- Added Fast FORTRAN Processor instructions
- Added SET OFFLINE/ONLINE and SET UNLOAD/LOAD commands to tapes and disks

2. Bugs Fixed in 3.4-0

2.1 Interdata

- Fixed bug in show history routine (from Mark Hittinger)
- Fixed bug in initial memory allocation

2.2 PDP-10

- Fixed TU bug, ERASE and WREOF should not clear done (reported by
  Rich Alderson)
- Fixed TU error reporting

2.3 PDP-11

- Fixed TU error reporting
This commit is contained in:
Bob Supnik 2005-05-03 04:10:00 -07:00 committed by Mark Pizzolato
parent 098200a126
commit ec60bbf329
62 changed files with 4332 additions and 7632 deletions

View file

@ -1,47 +0,0 @@
Notes For V3.3-2
1. New Features in 3.3-2
1.1 SCP and Libraries
- Added ASSERT command (from Dave Bryan)
1.2 PDP-11, VAX
- Added RA60, RA71, RA81 disks
2. Bugs Fixed in 3.3-2
2.1 H316
- Fixed IORETURN macro
- PT: fixed bug in OCP '0001 (found by Philipp Hachtmann)
- MT: fixed error reporting from OCP (found by Philipp Hachtmann)
2.2 Interdata 32b
- Fixed branches to mask new PC (from Greg Johnson)
2.3 PDP-11
- Fixed bugs in RESET for 11/70 (reported by Tim Chapman)
- Fixed bug in SHOW MODEL (from Sergey Okhapkin)
- Made SYSID variable for 11/70 (from Tim Chapman)
- Fixed MBRK write case for 11/70 (from Tim Chapman)
- RY: fixed bug in boot code (reported by Graham Toal)
2.4 VAX
- Fixed initial state of cpu_extmem
2.5 HP2100 (from Dave Bryan)
- Fixed missing MPCK on JRS target
- Removed EXECUTE instruction (is NOP in actual microcode)
- Fixed missing negative overflow renorm in StoreFP
2.6 I1401
- Fixed bug in line printer write line (reported by Van Snyder)

38
0readme_34.txt Normal file
View file

@ -0,0 +1,38 @@
Notes For V3.4-0
The memory layout for the Interdata simulators has been changed.
Do not use Interdata SAVE files from prior revisions with V3.4.
1. New Features in 3.4
1.1 SCP and Libraries
- Revised interpretation of fprint_sym, fparse_sym returns
- Revised syntax for SET DEBUG
- DO command nesting allowed to ten levels
1.2 Interdata
- Revised memory model to be 16b instead of 8b
1.3 HP2100
- Added Fast FORTRAN Processor instructions
- Added SET OFFLINE/ONLINE and SET UNLOAD/LOAD commands to tapes and disks
2. Bugs Fixed in 3.4-0
2.1 Interdata
- Fixed bug in show history routine (from Mark Hittinger)
- Fixed bug in initial memory allocation
2.2 PDP-10
- Fixed TU bug, ERASE and WREOF should not clear done (reported by
Rich Alderson)
- Fixed TU error reporting
2.3 PDP-11
- Fixed TU error reporting

File diff suppressed because it is too large Load diff

View file

@ -1,6 +1,6 @@
/* altairz80_defs.h: MITS Altair simulator definitions
Copyright (c) 2002-2004, Peter Schorn
Copyright (c) 2002-2005, Peter Schorn
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
@ -36,15 +36,15 @@
#define BANKMASK (MAXBANKS-1) /* bank mask */
#define MEMSIZE (cpu_unit.capac) /* actual memory size */
#define KB 1024 /* kilo byte */
#define defaultROMLow 0xff00 /* default for lowest addres of ROM */
#define defaultROMHigh 0xffff /* default for highest addres of ROM */
#define defaultROMLow 0xff00 /* default for lowest address of ROM */
#define defaultROMHigh 0xffff /* default for highest address of ROM */
#define NUM_OF_DSK 8 /* NUM_OF_DSK must be power of two */
#define LDAInstruction 0x3e /* op-code for LD A,<8-bit value> instruction */
#define unitNoOffset1 0x37 /* LD A,<unitno> */
#define unitNoOffset2 0xb4 /* LD a,80h | <unitno> */
#define UNIT_V_OPSTOP (UNIT_V_UF+0) /* stop on nvalid operation */
#define UNIT_V_OPSTOP (UNIT_V_UF+0) /* stop on invalid operation */
#define UNIT_OPSTOP (1 << UNIT_V_OPSTOP)
#define UNIT_V_CHIP (UNIT_V_UF+1) /* 8080 or Z80 CPU */
#define UNIT_CHIP (1 << UNIT_V_CHIP)

View file

@ -1,6 +1,6 @@
/* altairz80_dsk.c: MITS Altair 88-DISK Simulator
Copyright (c) 2002-2004, Peter Schorn
Copyright (c) 2002-2005, Peter Schorn
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
@ -30,7 +30,7 @@
Each diskette has physically 77 tracks of 32 137-byte sectors
each.
The controller is interfaced to the CPU by use of 3 I/O addreses,
The controller is interfaced to the CPU by use of 3 I/O addresses,
standardly, these are device numbers 10, 11, and 12 (octal).
Address Mode Function

View file

@ -1,6 +1,6 @@
/* altairz80_sio: MITS Altair serial I/O card
Copyright (c) 2002-2004, Peter Schorn
Copyright (c) 2002-2005, Peter Schorn
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
@ -58,7 +58,7 @@
#define UNIT_V_ANSI (UNIT_V_UF + 0) /* ANSI mode, strip bit 8 on output */
#define UNIT_ANSI (1 << UNIT_V_ANSI)
#define UNIT_V_UPPER (UNIT_V_UF + 1) /* uppper case mode */
#define UNIT_V_UPPER (UNIT_V_UF + 1) /* upper case mode */
#define UNIT_UPPER (1 << UNIT_V_UPPER)
#define UNIT_V_BS (UNIT_V_UF + 2) /* map delete to backspace */
#define UNIT_BS (1 << UNIT_V_BS)
@ -170,7 +170,7 @@ static int32 warnUnattachedPTR = 0; /* display a warning message if < warnLe
static int32 warnPTREOF = 0; /* display a warning message if < warnLevel and SIO set to
VERBOSE and attempt to read from PTR past EOF */
static int32 warnUnassignedPort = 0; /* display a warning message if < warnLevel and SIO set to
VERBOSE andattempt to perform IN or OUT on an unassigned PORT */
VERBOSE and attempt to perform IN or OUT on an unassigned PORT */
struct sio_terminal {
int32 data; /* data for this terminal */
int32 status; /* status information for this terminal */
@ -743,10 +743,10 @@ static t_stat simh_svc(UNIT *uptr) {
return SCPE_OK;
}
/* The CP/M commandline is used as the name of a file and UNIT* uptr is attached to it. */
/* The CP/M command line is used as the name of a file and UNIT* uptr is attached to it. */
static void attachCPM(UNIT *uptr) {
char cpmCommandLine[cpmCommandLineLength];
uint32 i, len = (GetBYTEWrapper(0x80) & 0x7f) - 1; /* 0x80 contains length of commandline, discard first char */
uint32 i, len = (GetBYTEWrapper(0x80) & 0x7f) - 1; /* 0x80 contains length of command line, discard first char */
for (i = 0; i < len; i++) {
cpmCommandLine[i] = (char)GetBYTEWrapper(0x82 + i); /* the first char, typically ' ', is discarded */
}

View file

@ -1,6 +1,6 @@
/* altairz80_sys.c: MITS Altair system interface
Copyright (c) 2002-2004, Peter Schorn
Copyright (c) 2002-2005, Peter Schorn
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
@ -425,7 +425,7 @@ int32 fprint_sym(FILE *of, int32 addr, uint32 *val, UNIT *uptr, int32 sw) {
return 1 - ch; /* need to return additional bytes */
}
/* numString checks determines the base of the number (ch, *numString)
/* checkbase determines the base of the number (ch, *numString)
and returns FALSE if the number is bad */
static int32 checkbase(char ch, const char *numString) {
int32 decimal = (ch <= '9');
@ -475,7 +475,7 @@ static int32 match(const char *pattern, const char *input, char *xyFirst, char *
char inp = *input++;
while ((pat) && (inp)) {
switch(pat) {
case '_': /* patterns containting '_' should never match */
case '_': /* patterns containing '_' should never match */
return FALSE;
case ',':
if (inp == ' ') {

View file

@ -1,13 +1,13 @@
To: Users
From: Peter Schorn
Subj: AltairZ80 Simulator Usage
Date: 12-Apr-2004
Date: 05-Apr-2005
COPYRIGHT NOTICE
The following copyright notice applies to both the SIMH source and binary:
Copyright (c) 2002-2004, Peter Schorn
Copyright (c) 2002-2005, Peter Schorn
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
@ -61,7 +61,10 @@ sim/AltairZ80/altairz80_defs.h
2. Revision History
- 12-Apr-2004, Peter Schorn (added MAP/NOMAP capability to switch off key mapping)
- 05-Apr-2005, removed bogus t-state stepping support
- 24-Jul-2004, Peter Schorn (updated CP/M 2 and SPL packages)
- 12-Apr-2004, Peter Schorn (added MAP/NOMAP capability to switch off
key mapping)
- 26-Jan-2004, Peter Schorn (added support for t-state stepping)
- 25-Feb-2003, Peter Schorn (added support for real time simulation)
- 9-Oct-2002, Peter Schorn (added support for simulated hard disk)
@ -169,7 +172,7 @@ the MITS Disk Basic and Altair DOS require about a minimum of 24K.
a warning message if the CPU attempts to read from non-existing
memory.
SET CPU NOWARNROM Suppreses all warning message of "WARNROM". Note that
SET CPU NOWARNROM Suppresses all warning message of "WARNROM". Note that
some software tries on purpose to write to ROM in order to detect
the available RAM.
@ -181,7 +184,7 @@ crashes. This is historically accurate behavior.
The real 8080, on receiving a HLT (Halt) instruction, freezes the
processor and only an interrupt or CPU hardware reset will restore it. The
simulator is alot nicer, it will halt but send you back to the simulator
simulator is a lot nicer, it will halt but send you back to the simulator
command line.
CPU Registers include the following:
@ -193,7 +196,7 @@ CPU Registers include the following:
F = S Z - AC - P/V N C
S = Sign flag.
Z = Zero Flag.
AC = Auxillary Carry flag.
AC = Auxiliary Carry flag.
P/V = Parity flag on 8080
Parity / Overflow flag on Z80
- = not used (undefined)
@ -307,10 +310,10 @@ for debugging purposes.
The MITS 88-DISK is a simple programmed I/O interface to the MITS 8-inch
floppy drive, which was basically a Pertec FD-400 with a power supply and
buffer board builtin. The controller supports neither interrupts nor DMA,
buffer board built-in. The controller supports neither interrupts nor DMA,
so floppy access required the sustained attention of the CPU. The standard
I/O addresses were 8, 9, and 0A (hex), and we follow the standard. Details
on controlling this hardware are in the altair_dsk.c source file.
on controlling this hardware are in the altairz80_dsk.c source file.
The only difference is that the simulated disks may be larger than the
original ones: The original disk had 77 tracks while the simulated disks
@ -438,10 +441,10 @@ DUMP .COM 2K ; hex dump a file
ED .COM 8K ; line editor
ELIZA .BAS 10K ; Eliza game in Basic
EX8080 .COM 12K ; exercise 8080 instruction set
EXZ80N .COM 12K ; exercise Z80 instruction set, No undefined status bits
EXZ80U .COM 12K ; exercise Z80 instruction set, Undefined status bits
EXZ80 .MAC 54K ; source for EX8080.COM, EXZ80N.COM, EXZ80U.COM
EX .SUB 2K ; benchmark execution of EX8080.COM, EXZ80N.COM, EXZ80U.COM
EXZ80DOC.COM 12K ; exercise Z80 instruction set, No undefined status bits
EXZ80ALL.COM 12K ; exercise Z80 instruction set, Undefined status bits
EX .MAC 54K ; source for EX8080.COM, EXZ80DOC.COM, EXZ80ALL.COM
EX .SUB 2K ; benchmark execution of EX8080.COM,EXZ80DOC.COM,EXZ80ALL.COM
FORMAT .COM 2K ; format disks
GO .COM 0K ; start the currently loaded program at 100H
HDSKBOOT.MAC 6K ; boot code for hard disk
@ -484,7 +487,7 @@ W .COM 4K ; write files to SIMH environment
WM .COM 12K ; word master screen editor
WM .HLP 3K ; help file for WM.COM
WORM .COM 4K ; worm game for VT100 terminal
XFORMAT .COM 2K ; initialise a drive (floppy or hard disk)
XFORMAT .COM 2K ; initialize a drive (floppy or hard disk)
XSUB .COM 2K ; support for DO.COM
ZAP .COM 10K ; SuperZap 5.2 disk editor configured for VT100
ZSID .COM 10K ; debugger for Z80
@ -493,7 +496,7 @@ ZTRAN4 .COM 4K ; translate 8080 mnemonics into Z80 equivalents
5.2 CP/M Version 3 with banked memory
CP/M 3 is the successor to CP/M 2.2. A customised BIOS (BIOS3.MAC) is
CP/M 3 is the successor to CP/M 2.2. A customized BIOS (BIOS3.MAC) is
included to facilitate modification if so desired. The defaults supplied in
GENCPM.DAT for system generation can be used. BOOTGEN.COM is used to place
the CP/M loader (LDR.COM) on the boot tracks of a disk.
@ -545,13 +548,13 @@ HEXCOM .CPM 2K
HIST .UTL 2K
INITDIR .COM 32K
L80 .COM 12K ; Microsoft linker
LDR .COM 4K ; CP/M loader with optimised loader BIOS
LDRBIOS3.MAC 14K ; optimised (for space) loader BIOS
LDR .COM 4K ; CP/M loader with optimized loader BIOS
LDRBIOS3.MAC 14K ; optimized (for space) loader BIOS
LIB .COM 8K ; Digital Research librarian
LINK .COM 16K ; Digital Research linker
LOAD .COM 2K
M80 .COM 20K ; Microsoft macro assembler
MC .SUB 2K ; assemble and link an assmbler program
MC .SUB 2K ; assemble and link an assembler program
MCC .SUB 2K ; read, assemble and link an assembler program
PATCH .COM 4K
PIP .COM 10K ; Peripheral Interchange Program
@ -626,7 +629,7 @@ DUMP .MAC 6K ; source for DUMP.PRL
DUMP .PRL 2K ; dump command
ED .PRL 10K ; MP/M line editor
ERA .PRL 2K ; erase command
ERAQ .PRL 4K ; erase comand (verbose)
ERAQ .PRL 4K ; erase command (verbose)
GENHEX .COM 2K
GENMOD .COM 2K
GENSYS .COM 10K
@ -636,7 +639,7 @@ LIB .COM 8K ; library utility
LINK .COM 16K ; linker
LOAD .COM 2K ; loader
M80 .COM 20K ; Microsoft macro assembler
MC .SUB 2K ; assemble and link an assmbler program
MC .SUB 2K ; assemble and link an assembler program
MCC .SUB 2K ; read, assemble and link an assembler program
MPM .COM 8K ; start MP/M II
MPM .SYS 26K ; MP/M system file
@ -703,21 +706,22 @@ before booting CP/M.
The disk "app.dsk" contains the following files:
Name Ext Size Comment
ACKER .SPL 4K ; compute the Ackermann function
ACKER .COM 2K ; compute the Ackermann function, SPL source
BOOTGEN .COM 2K
BOOTGEN .SPL 6K ; SPL source for BOOTGEN.COM
C .SUB 2K ; batch file for compiling an SPL source file
CALC .PRO 4K ; Prolog demo program: Calculator
CC .SUB 2K ; compile an SPL source which is on the underlying
file system
DECLARAT. 12K ; common include file, SPL source
DIF .COM 4K
DIF .SPL 10K ; SPL source for DIF.COM
EDIT .SPL 10K ; screen editor for PROLOGZ, SPL source
FAC .COM 4K ; compute the factorial
FAC .SPL 4K ; compute the factorial, SPL source
FAMILY .PRO 4K ; Prolog demo program: Family relations
FORMEL .COM 4K ; calculator
FORMEL .SPL 6K ; calculator, SPL source
INTEGER .PRO 2K ; Prolog demo program: Integer arithmetic
KNAKE .PRO 2K ; Prolog demo program: Logic puzzle
LINKMT .COM 12K ; Pascal MT+ 5.5 linker
MAIN .SPL 14K ; main module for PROLOGZ, SPL source
MOVE .MAC 4K ; helper functions for PROLOGZ in assembler
MTERRS .TXT 6K ; Pascal MT+ error messages
MTPLUS .000 14K ; Pascal MT+ 5.5 compiler file
@ -733,34 +737,31 @@ PASCFORM.PAS 54K ; Pascal formatter source code
PASCFORM.SUB 2K ; create Pascal formatter
PASLIB .ERL 24K ; Pascal MT+ 5.5 run time library
PINST .COM 4K ; terminal installation program for PROLOGZ
PINST .SPL 16K ; terminal installation program for PROLOGZ,
SPL source
PINST .SPL 16K ; terminal installation program for PROLOGZ, SPL source
PRIM .COM 2K ; compute prime numbers
PRIM .SPL 2K ; compute prime numbers, SPL source
PROLOGZ .COM 18K ; PROLOGZ interpreter and screen editor
PROLOGZ .SPL 2K ; PROLOGZ main program, SPL source
PROLOGZ .SPL 2K ; SPL source for PROLOGZ
PROLOGZ .TXT 40K ; PROLOGZ documentation in German
PROVE .SPL 16K ; backtrack theorem prover for PROLOGZ, SPL source
PZCLEAN .SUB 2K ; PROLOGZ: remove all created ".rel" and ".lst" files
PZLINK .SUB 2K ; PROLOGZ: create PINST, PROLOGZ and personalise the
serial number
PZMAKE .SUB 2K ; PROLOGZ: compiles the sources (you can ignore
any compiler errors)
QUEEN .PRO 2K ; Prolog demo program: N-queens problem
READ .COM 4K
READ .SPL 10K ; SPL source for R.COM
SHOWSEC .COM 4K
RELDUMP .COM 4K ; dump a .REL file to the console
RELDUMP .SPL 10K ; dump a .REL file to the console, SPL source
SHOWSEC .COM 2K
SHOWSEC .SPL 6K ; SPL source for SHOWSEC.COM
SIEVE .COM 2K ; compute prime numbers with a sieve
SIEVE .SPL 6K ; compute prime numbers with a sieve, SPL source
SPEED .COM 2K ; utility to measure the clock speed of the simulated CPU
SPEED .SPL 2K ; SPL source for SPEED.COM, requires SWLIB.MAC
SPL .COM 38K ; the SPL compiler itself
SPL .TXT 56K ; SPL language and compiler documentation in German
SPLERROR.DAT 12K ; error messages of the compiler (in German)
SPLIB .REL 6K ; SPL runtime library
STDIO . 2K ; include file for SPL programs
SWLIB .MAC 2K ; assembler utility routines needed by SPEED.SPL
SPEED .SPL 4K ; SPL source for SPEED.COM
SPL .COM 28K ; the SPL compiler itself
SPL .TXT 50K ; SPL language and compiler documentation
SPLERROR.DAT 8K ; error messages of the compiler
SPLRTLB .REL 2K ; SPL runtime library
SYSCOPY .COM 2K
SYSCOPY .SPL 6K ; SPL source for SYSCOPY.COM
TERMBDOS.SPL 2K ; terminal interface to CP/M for PROLOGZ, SPL source
UTIL .SPL 18K ; utility functions for PROLOGZ, SPL source
WC .COM 6K ; word count and query facility
WC .SPL 14K ; word count and query facility, SPL source
WRITE .COM 4K
WRITE .SPL 8K ; SPL source for W.COM
XFORMAT .COM 2K
@ -828,7 +829,7 @@ trick is to get the Switch Register right).
sim> set cpu 8080 ;note 4k Basic will not run on a Z80 CPU
sim> set sio upper ;4k Basic does not like lower case letters as input
sim> set cpu noitrap ;4k Basic likes to execute non 8080 instructions - ignore
sim> set cpu noitrap ;4k Basic likes to execute non 8080 instructions-ignore
sim> set sio ansi ;4k Basic produces 8-bit output, strip to seven bits
sim> d sr 8 ;good setting for the Switch Register
sim> load 4kbas.bin 0 ;load it at 0
@ -873,8 +874,8 @@ trick is to get the Switch Register right).
Execute the following commands to run Altair Extended Basic:
sim> set sio upper ;Extended Basic does not like lower case letters as input
sim> set sio ansi ;Extended Basic produces 8-bit output, strip to seven bits
sim> set sio upper ;Extended Basic requires upper case input
sim> set sio ansi ;Extended Basic produces 8-bit output, strip to 7 bits
sim> d sr 8 ;good setting for the Switch Register
sim> load exbas.bin 0 ;load it at 0
sim> go 0 ;and start it
@ -914,10 +915,7 @@ following commands:
OK
6. Special simulator features
6.1 Memory access breakpoints
6. Special simulator feature: Memory access breakpoints
In addition to the regular SIMH features such as PC queue, breakpoints
etc., this simulator supports memory access breakpoints. A memory access
@ -932,21 +930,6 @@ a memory access breakpoint is not triggered by fetching code from memory
by using the typing facility of the SIMH breakpoints.
6.2 T-state stepping
The SIMH step command supports the "-t" modifier to allow steppping for
a predefined number of t-states. For example
sim> step -t 1000
will cause the simulated CPU to execute 1000 t-states (note that the shortest
instruction will have 4 t-states). On the other hand, the command
sim> step 1000
will cause the simulated CPU to execute 1000 instructions.
7. Brief summary of all major changes to the original Altair simulator
- Full support for Z80. CP/M software requiring a Z80 CPU now runs
properly. DDTZ and PROLOGZ are included for demonstration purposes.

View file

@ -1,6 +1,6 @@
/* altairz80_hdsk.c: simulated hard disk device to increase capacity
Copyright (c) 2002-2004, Peter Schorn
Copyright (c) 2002-2005, Peter Schorn
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),

View file

@ -27,6 +27,7 @@
MP 12892B memory protect
DMA0,DMA1 12895A/12897B direct memory access/dual channel port controller
21-Jan-05 JDB Reorganized CPU option flags
15-Jan-05 RMS Split out EAU and MAC instructions
26-Dec-04 RMS DMA reset doesn't clear alternate CTL flop (from Dave Bryan)
DMA reset shouldn't clear control words (from Dave Bryan)
@ -340,9 +341,16 @@
#define UNIT_MP_INT (1 << UNIT_V_MP_INT)
#define UNIT_MP_SEL1 (1 << UNIT_V_MP_SEL1)
#define MOD_2116 1
#define MOD_2100 2
#define MOD_21MX 4
#define MOD_211X (1 << TYPE_211X)
#define MOD_2100 (1 << TYPE_2100)
#define MOD_21MX (1 << TYPE_21MX)
#define MOD_CURRENT (1 << CPU_TYPE)
#define UNIT_SYSTEM (UNIT_CPU_MASK | UNIT_OPTS)
#define UNIT_SYS_2116 (UNIT_2116)
#define UNIT_SYS_2100 (UNIT_2100 | UNIT_EAU)
#define UNIT_SYS_21MX_M (UNIT_21MX_M | UNIT_EAU | UNIT_FP | UNIT_DMS)
#define UNIT_SYS_21MX_E (UNIT_21MX_E | UNIT_EAU | UNIT_FP | UNIT_DMS)
#define ABORT(val) longjmp (save_env, (val))
@ -396,13 +404,14 @@ struct opt_table { /* options table */
int32 cpuf; };
static struct opt_table opt_val[] = {
{ UNIT_EAU, MOD_2116 },
{ UNIT_EAU, MOD_211X },
{ UNIT_FP, MOD_2100 },
{ UNIT_DMS, MOD_21MX },
{ UNIT_IOP, MOD_2100 | MOD_21MX },
{ UNIT_2116, MOD_2116 | MOD_2100 | MOD_21MX },
{ UNIT_2100, MOD_2116 | MOD_2100 | MOD_21MX },
{ UNIT_21MX, MOD_2116 | MOD_2100 | MOD_21MX },
{ UNIT_FFP, MOD_2100 | MOD_21MX },
{ TYPE_211X, MOD_211X | MOD_2100 | MOD_21MX },
{ TYPE_2100, MOD_211X | MOD_2100 | MOD_21MX },
{ TYPE_21MX, MOD_211X | MOD_2100 | MOD_21MX },
{ 0, 0 } };
extern int32 sim_interval;
@ -415,7 +424,7 @@ extern DEVICE *sim_devices[];
extern int32 sim_switches;
extern char halt_msg[];
t_stat Ea1 (uint32 *addr, uint32 irq);
t_stat Ea (uint32 IR, uint32 *addr, uint32 irq);
uint16 ReadIO (uint32 addr, uint32 map);
uint16 ReadPW (uint32 addr);
uint16 ReadTAB (uint32 addr);
@ -440,7 +449,8 @@ t_bool dev_conflict (void);
void hp_post_cmd (t_bool from_scp);
extern t_stat cpu_eau (uint32 IR, uint32 intrq);
extern t_stat cpu_mac (uint32 IR, uint32 intrq);
extern t_stat cpu_uig_0 (uint32 IR, uint32 intrq);
extern t_stat cpu_uig_1 (uint32 IR, uint32 intrq);
extern int32 clk_delay (int32 flg);
extern void (*sim_vm_post) (t_bool from_scp);
@ -495,49 +505,50 @@ REG cpu_reg[] = {
{ NULL } };
MTAB cpu_mod[] = {
{ UNIT_2116+UNIT_2100+UNIT_21MX+UNIT_EAU+UNIT_FP+UNIT_DMS+UNIT_IOP+UNIT_IOPX,
UNIT_2116, NULL, "2116", &cpu_set_opt,
NULL, (void *) UNIT_2116 },
{ UNIT_2116+UNIT_2100+UNIT_21MX+UNIT_EAU+UNIT_FP+UNIT_DMS+UNIT_IOP+UNIT_IOPX,
UNIT_2100+UNIT_EAU, NULL, "2100", &cpu_set_opt,
NULL, (void *) UNIT_2100 },
{ UNIT_2116+UNIT_2100+UNIT_21MX+UNIT_MXM+UNIT_EAU+UNIT_FP+UNIT_DMS+UNIT_IOP+UNIT_IOPX,
UNIT_21MX+UNIT_EAU+UNIT_FP+UNIT_DMS, NULL, "21MX-E", &cpu_set_opt,
NULL, (void *) UNIT_21MX },
{ UNIT_2116+UNIT_2100+UNIT_21MX+UNIT_MXM+UNIT_EAU+UNIT_FP+UNIT_DMS+UNIT_IOP+UNIT_IOPX,
UNIT_21MX+UNIT_MXM+UNIT_EAU+UNIT_FP+UNIT_DMS, NULL, "21MX-M", &cpu_set_opt,
NULL, (void *) UNIT_21MX },
{ UNIT_2116+UNIT_2100+UNIT_21MX, UNIT_2116, "2116", NULL, NULL },
{ UNIT_2116+UNIT_2100+UNIT_21MX, UNIT_2100, "2100", NULL, NULL },
{ UNIT_2116+UNIT_2100+UNIT_21MX+UNIT_MXM, UNIT_21MX, "21MX-E", NULL, NULL },
{ UNIT_2116+UNIT_2100+UNIT_21MX+UNIT_MXM, UNIT_21MX+UNIT_MXM, "21MX-M", NULL, NULL },
{ UNIT_EAU, UNIT_EAU, "EAU", "EAU", &cpu_set_opt,
NULL, (void *) UNIT_EAU },
{ UNIT_EAU, 0, "no EAU", "NOEAU", &cpu_set_opt,
NULL, (void *) UNIT_EAU },
{ UNIT_FP, UNIT_FP, "FP", "FP", &cpu_set_opt,
NULL, (void *) UNIT_FP },
{ UNIT_FP, 0, "no FP", "NOFP", &cpu_set_opt,
NULL, (void *) UNIT_FP },
{ UNIT_DMS, UNIT_DMS, "DMS", "DMS", &cpu_set_opt,
NULL, (void *) UNIT_DMS },
{ UNIT_DMS, 0, "no DMS", "NODMS", &cpu_set_opt,
NULL, (void *) UNIT_DMS },
{ UNIT_MSIZE, 2, NULL, "IOP", &cpu_set_opt,
NULL, (void *) UNIT_IOP },
{ UNIT_IOP+UNIT_IOPX, UNIT_IOP, "IOP", NULL, NULL },
{ UNIT_IOP+UNIT_IOPX, UNIT_IOPX,"IOP", NULL, NULL },
{ UNIT_IOP+UNIT_IOPX, 0, "no IOP", "NOIOP", &cpu_set_opt,
NULL, (void *) UNIT_IOP },
{ UNIT_MSIZE, 4096, NULL, "4K", &cpu_set_size },
{ UNIT_MSIZE, 8192, NULL, "8K", &cpu_set_size },
{ UNIT_MSIZE, 16384, NULL, "16K", &cpu_set_size },
{ UNIT_MSIZE, 32768, NULL, "32K", &cpu_set_size },
{ UNIT_MSIZE, 65536, NULL, "64K", &cpu_set_size },
{ UNIT_MSIZE, 131072, NULL, "128K", &cpu_set_size },
{ UNIT_MSIZE, 262144, NULL, "256K", &cpu_set_size },
{ UNIT_MSIZE, 524288, NULL, "512K", &cpu_set_size },
{ UNIT_MSIZE, 1048576, NULL, "1024K", &cpu_set_size },
{ UNIT_SYSTEM, UNIT_SYS_2116, NULL, "2116", &cpu_set_opt, NULL,
(void *) TYPE_211X },
{ UNIT_SYSTEM, UNIT_SYS_2100, NULL, "2100", &cpu_set_opt, NULL,
(void *) TYPE_2100 },
{ UNIT_SYSTEM, UNIT_SYS_21MX_E, NULL, "21MX-E", &cpu_set_opt, NULL,
(void *) TYPE_21MX },
{ UNIT_SYSTEM, UNIT_SYS_21MX_M, NULL, "21MX-M", &cpu_set_opt, NULL,
(void *) TYPE_21MX },
{ UNIT_CPU_MASK, UNIT_2116, "2116", NULL, NULL },
{ UNIT_CPU_MASK, UNIT_2100, "2100", NULL, NULL },
{ UNIT_CPU_MASK, UNIT_21MX_E, "21MX-E", NULL, NULL },
{ UNIT_CPU_MASK, UNIT_21MX_M, "21MX-M", NULL, NULL },
{ UNIT_EAU, UNIT_EAU, "EAU", "EAU", &cpu_set_opt, NULL,
(void *) UNIT_EAU },
{ UNIT_EAU, 0, "no EAU", "NOEAU", &cpu_set_opt, NULL,
(void *) UNIT_EAU },
{ UNIT_FP, UNIT_FP, "FP", "FP", &cpu_set_opt, NULL,
(void *) UNIT_FP },
{ UNIT_FP, 0, "no FP", "NOFP", &cpu_set_opt, NULL,
(void *) UNIT_FP },
{ UNIT_IOP, UNIT_IOP, "IOP", "IOP", &cpu_set_opt, NULL,
(void *) UNIT_IOP },
{ UNIT_IOP, 0, "no IOP", "NOIOP", &cpu_set_opt, NULL,
(void *) UNIT_IOP },
{ UNIT_DMS, UNIT_DMS, "DMS", "DMS", &cpu_set_opt, NULL,
(void *) UNIT_DMS },
{ UNIT_DMS, 0, "no DMS", "NODMS", &cpu_set_opt, NULL,
(void *) UNIT_DMS },
{ UNIT_FFP, UNIT_FFP, "FFP", "FFP", &cpu_set_opt, NULL,
(void *) UNIT_FFP },
{ UNIT_FFP, 0, "no FFP", "NOFFP", &cpu_set_opt, NULL,
(void *) UNIT_FFP },
{ MTAB_XTD | MTAB_VDV, 4096, NULL, "4K", &cpu_set_size },
{ MTAB_XTD | MTAB_VDV, 8192, NULL, "8K", &cpu_set_size },
{ MTAB_XTD | MTAB_VDV, 16384, NULL, "16K", &cpu_set_size },
{ MTAB_XTD | MTAB_VDV, 32768, NULL, "32K", &cpu_set_size },
{ MTAB_XTD | MTAB_VDV, 65536, NULL, "64K", &cpu_set_size },
{ MTAB_XTD | MTAB_VDV, 131072, NULL, "128K", &cpu_set_size },
{ MTAB_XTD | MTAB_VDV, 262144, NULL, "256K", &cpu_set_size },
{ MTAB_XTD | MTAB_VDV, 524288, NULL, "512K", &cpu_set_size },
{ MTAB_XTD | MTAB_VDV, 1048576, NULL, "1024K", &cpu_set_size },
{ 0 } };
DEVICE cpu_dev = {
@ -1006,10 +1017,15 @@ case 0211: /* DST */
/* Extended instructions */
case 0212: /* MAC0 ext */
case 0203: /* MAC1 ext */
case 0212: /* UIG 0 extension */
reason = cpu_uig_0 (IR, intrq); /* extended opcode */
dmarq = calc_dma (); /* recalc DMA masks */
intrq = calc_int (); /* recalc interrupts */
break;
case 0203: /* UIG 1 extension */
case 0213:
reason = cpu_mac (IR, intrq); /* extended opcode */
reason = cpu_uig_1 (IR, intrq); /* extended opcode */
dmarq = calc_dma (); /* recalc DMA masks */
intrq = calc_int (); /* recalc interrupts */
break; } /* end case IR */
@ -1043,14 +1059,12 @@ pcq_r->qptr = pcq_p; /* update pc q ptr */
return reason;
}
/* Effective address calculation */
/* Resolve indirect addresses */
t_stat Ea (uint32 IR, uint32 *addr, uint32 irq)
t_stat resolve (uint32 MA, uint32 *addr, uint32 irq)
{
uint32 i, MA;
uint32 i;
MA = IR & (I_IA | I_DISP); /* ind + disp */
if (IR & I_CP) MA = ((PC - 1) & I_PAGENO) | MA; /* current page? */
for (i = 0; (i < ind_max) && (MA & I_IA); i++) { /* resolve multilevel */
if (irq && /* int req? */
((i >= 2) || (mp_unit.flags & UNIT_MP_INT)) && /* ind > 3 or W6 out? */
@ -1062,23 +1076,15 @@ if (i >= ind_max) return STOP_IND; /* indirect loop? */
return SCPE_OK;
}
/* Effective address, two words */
/* Get effective address from IR */
t_stat Ea1 (uint32 *addr, uint32 irq)
t_stat Ea (uint32 IR, uint32 *addr, uint32 irq)
{
uint32 i, MA;
uint32 MA;
MA = ReadW (PC); /* get next address */
PC = (PC + 1) & VAMASK;
for (i = 0; (i < ind_max) && (MA & I_IA); i++) { /* resolve multilevel */
if (irq && /* int req? */
((i >= 2) || (mp_unit.flags & UNIT_MP_INT)) && /* ind > 3 or W6 out? */
!(mp_unit.flags & DEV_DIS)) /* MP installed? */
return STOP_INDINT; /* break out */
MA = ReadW (MA & VAMASK); }
if (i >= ind_max) return STOP_IND; /* indirect loop? */
*addr = MA;
return SCPE_OK;
MA = IR & (I_IA | I_DISP); /* ind + disp */
if (IR & I_CP) MA = ((PC - 1) & I_PAGENO) | MA; /* current page? */
return resolve (MA, addr, irq); /* resolve indirects */
}
/* Shift micro operation */
@ -1181,7 +1187,7 @@ return r;
to request an interrupt. This is the masked under the
result from #1 to determine the highest priority interrupt,
if any.
*/
*/
uint32 calc_int (void)
{
@ -1550,7 +1556,7 @@ case ioLIX: /* load */
dat = SR;
break;
case ioOTX: /* output */
if (cpu_unit.flags & (UNIT_2100 | UNIT_21MX)) SR = dat;
if (UNIT_CPU_TYPE != UNIT_TYPE_211X) SR = dat;
break;
default:
break; }
@ -1663,7 +1669,7 @@ case ioSFS: /* skip flag set */
case ioLIX: /* load */
dat = 0;
case ioMIX: /* merge */
if (cpu_unit.flags & UNIT_21MX) dat = DMASK;
if (UNIT_CPU_TYPE == UNIT_TYPE_21MX) dat = DMASK;
break;
case ioOTX: /* output */
dmac[ch].cw1 = dat;
@ -1748,7 +1754,8 @@ case ioSFC: /* skip flag clear */
case ioLIX: /* load */
dat = 0;
case ioMIX: /* merge */
if ((devd < VARDEV) && (cpu_unit.flags & UNIT_21MX)) dat = DMASK;
if ((devd < VARDEV) && (UNIT_CPU_TYPE == UNIT_TYPE_21MX))
dat = DMASK;
break;
default:
break; }
@ -1854,7 +1861,7 @@ int32 mc = 0;
uint32 i;
if ((val <= 0) || (val > PASIZE) || ((val & 07777) != 0) ||
(!(uptr->flags & UNIT_21MX) && (val > VASIZE)))
((UNIT_CPU_TYPE != UNIT_TYPE_21MX) && (val > VASIZE)))
return SCPE_ARG;
if (!(sim_switches & SWMASK ('F'))) { /* force truncation? */
for (i = val; i < MEMSIZE; i++) mc = mc | M[i];
@ -1947,33 +1954,35 @@ return FALSE;
/* Configuration validation
Memory is trimmed to 32K if 2116 or 2100 is selected.
Memory protect is enabled if 2100 or 21MX or DMS is selected.
DMA is enabled if 2116 or 2100 or 21MX is selected. */
- Checks that the current CPU type supports the option selected.
- Ensures that FP/FFP and IOP are mutually exclusive if CPU is 2100.
- Disables memory protect if 2116 is selected.
- Enables memory protect if 2100 or 21MX or DMS is selected.
- Enables DMA if 2116 or 2100 or 21MX is selected.
- Memory is trimmed to 32K if 2116 or 2100 is selected. */
t_bool cpu_set_opt (UNIT *uptr, int32 val, char *cptr, void *desc)
{
int32 opt = (int32) desc;
int32 mod, i;
int32 i;
uint32 mod;
mod = MOD_2116;
if (uptr->flags & UNIT_2100) mod = MOD_2100;
else if (uptr->flags & UNIT_21MX) mod = MOD_21MX;
mod = MOD_CURRENT;
for (i = 0; opt_val[i].cpuf != 0; i++) {
if ((opt == opt_val[i].optf) && (mod & opt_val[i].cpuf)) {
if ((mod == MOD_2100) && (val == UNIT_FP))
uptr->flags = uptr->flags & ~UNIT_IOP;
if ((opt == UNIT_IOP) && val) {
if (mod == MOD_2100)
uptr->flags = (uptr->flags & ~UNIT_FP) | UNIT_IOP;
if (mod == MOD_21MX) uptr->flags |= UNIT_IOPX; }
if (opt == UNIT_2116) mp_dev.flags = mp_dev.flags | DEV_DIS;
else if ((val == UNIT_DMS) || (opt == UNIT_2100) || (opt == UNIT_21MX))
if (mod == MOD_2100)
if ((opt == UNIT_FP) || (opt == UNIT_FFP))
uptr->flags = uptr->flags & ~UNIT_IOP;
else if (opt == UNIT_IOP)
uptr->flags = uptr->flags & ~(UNIT_FP | UNIT_FFP);
if (opt == TYPE_211X)
mp_dev.flags = mp_dev.flags | DEV_DIS;
else if ((opt == UNIT_DMS) || (opt == TYPE_2100) || (opt == TYPE_21MX))
mp_dev.flags = mp_dev.flags & ~DEV_DIS;
if ((opt == UNIT_2116) || (opt == UNIT_2100) || (opt == UNIT_21MX)) {
if ((opt == TYPE_211X) || (opt == TYPE_2100) || (opt == TYPE_21MX)) {
dma0_dev.flags = dma0_dev.flags & ~DEV_DIS;
dma1_dev.flags = dma1_dev.flags & ~DEV_DIS; }
if (((opt == UNIT_2116) || (opt == UNIT_2100)) && (MEMSIZE > VASIZE))
if (((opt == TYPE_211X) || (opt == TYPE_2100)) && (MEMSIZE > VASIZE))
return cpu_set_size (uptr, VASIZE, cptr, desc);
return SCPE_OK; } }
return SCPE_NOFNC;

View file

@ -23,37 +23,67 @@
be used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from Robert M Supnik.
21-Jan-05 JDB Reorganized CPU option flags
14-Jan-05 RMS Cloned from hp2100_cpu.c
CPU models are broken down into type and series to facilitate option
validation. Bits 3:2 encode the type, and bits 1:0 encode the series
within the type.
*/
#ifndef _HP2100_CPU_H_
#define _HP2100_CPU_H_ 0
#define CPU_V_SERIES 0
#define CPU_V_TYPE 2
#define TYPE_211X 0 /* 2114, 2115, 2116 */
#define TYPE_2100 1 /* 2100A, 2100S */
#define TYPE_21MX 2 /* 21MX-M, 21MX-E, 21MX-F */
#define TYPE_1000A 3 /* A600, A700, A900, A990 */
#define CPU_2116 (TYPE_211X << CPU_V_TYPE | 0)
#define CPU_2100 (TYPE_2100 << CPU_V_TYPE | 0)
#define CPU_21MX_M (TYPE_21MX << CPU_V_TYPE | 0)
#define CPU_21MX_E (TYPE_21MX << CPU_V_TYPE | 1)
#define UNIT_V_CPU (UNIT_V_UF + 0) /* CPU model bits 0-3 */
#define UNIT_M_CPU 017 /* CPU model mask */
#define UNIT_M_TYPE 014 /* CPU type mask */
#define UNIT_V_EAU (UNIT_V_UF + 4) /* EAU installed */
#define UNIT_V_FP (UNIT_V_UF + 5) /* FP installed */
#define UNIT_V_IOP (UNIT_V_UF + 6) /* IOP installed */
#define UNIT_V_DMS (UNIT_V_UF + 7) /* DMS installed */
#define UNIT_V_FFP (UNIT_V_UF + 8) /* FFP installed */
#define UNIT_CPU_MASK (UNIT_M_CPU << UNIT_V_CPU)
#define UNIT_2116 (CPU_2116 << UNIT_V_CPU)
#define UNIT_2100 (CPU_2100 << UNIT_V_CPU)
#define UNIT_21MX_M (CPU_21MX_M << UNIT_V_CPU)
#define UNIT_21MX_E (CPU_21MX_E << UNIT_V_CPU)
#define UNIT_TYPE_MASK (UNIT_M_TYPE << UNIT_V_CPU)
#define UNIT_TYPE_211X ((TYPE_211X << CPU_V_TYPE) << UNIT_V_CPU)
#define UNIT_TYPE_2100 ((TYPE_2100 << CPU_V_TYPE) << UNIT_V_CPU)
#define UNIT_TYPE_21MX ((TYPE_21MX << CPU_V_TYPE) << UNIT_V_CPU)
#define UNIT_CPU_MODEL (cpu_unit.flags & UNIT_CPU_MASK)
#define UNIT_CPU_TYPE (cpu_unit.flags & UNIT_TYPE_MASK)
#define CPU_TYPE (UNIT_CPU_TYPE >> (UNIT_V_CPU + CPU_V_TYPE))
#define UNIT_EAU (1 << UNIT_V_EAU)
#define UNIT_FP (1 << UNIT_V_FP)
#define UNIT_IOP (1 << UNIT_V_IOP)
#define UNIT_DMS (1 << UNIT_V_DMS)
#define UNIT_FFP (1 << UNIT_V_FFP)
#define UNIT_OPTS (UNIT_EAU | UNIT_FP | UNIT_IOP | UNIT_DMS | UNIT_FFP)
#define PCQ_SIZE 64 /* must be 2**n */
#define PCQ_MASK (PCQ_SIZE - 1)
#define PCQ_ENTRY pcq[pcq_p = (pcq_p - 1) & PCQ_MASK] = err_PC
#define UNIT_V_2100 (UNIT_V_UF + 0) /* 2100 */
#define UNIT_V_21MX (UNIT_V_UF + 1) /* 21MX-E or 21MX-M */
#define UNIT_V_EAU (UNIT_V_UF + 2) /* EAU */
#define UNIT_V_FP (UNIT_V_UF + 3) /* FP */
#define UNIT_V_DMS (UNIT_V_UF + 4) /* DMS */
#define UNIT_V_IOP (UNIT_V_UF + 5) /* 2100 IOP */
#define UNIT_V_IOPX (UNIT_V_UF + 6) /* 21MX IOP */
#define UNIT_V_MSIZE (UNIT_V_UF + 7) /* dummy mask */
#define UNIT_V_MXM (UNIT_V_UF + 8) /* 21MX is M-series */
#define UNIT_2116 (0)
#define UNIT_2100 (1 << UNIT_V_2100)
#define UNIT_21MX (1 << UNIT_V_21MX)
#define UNIT_EAU (1 << UNIT_V_EAU)
#define UNIT_FP (1 << UNIT_V_FP)
#define UNIT_DMS (1 << UNIT_V_DMS)
#define UNIT_IOP (1 << UNIT_V_IOP)
#define UNIT_IOPX (1 << UNIT_V_IOPX)
#define UNIT_MSIZE (1 << UNIT_V_MSIZE)
#define UNIT_MXM (1 << UNIT_V_MXM)
t_stat Ea (uint32 IR, uint32 *addr, uint32 irq);
t_stat resolve (uint32 MA, uint32 *addr, uint32 irq);
uint8 ReadB (uint32 addr);
uint8 ReadBA (uint32 addr);
uint16 ReadW (uint32 addr);

File diff suppressed because it is too large Load diff

View file

@ -63,7 +63,7 @@
#define MEM_ADDR_OK(x) (((uint32) (x)) < MEMSIZE)
#define VA_N_SIZE 15 /* virtual addr size */
#define VASIZE (1 << VA_N_SIZE)
#define VAMASK (VASIZE - 1) /* virt addr mask */
#define VAMASK 077777 /* virt addr mask */
#define PA_N_SIZE 20 /* phys addr size */
#define PASIZE (1 << PA_N_SIZE)
#define PAMASK (PASIZE - 1) /* phys addr mask */

View file

@ -1,6 +1,6 @@
SIMH/HP 21XX DIAGNOSTICS PERFORMANCE
====================================
Last update: 2004-12-29
Last update: 2005-03-22
The HP 24396 diagnostic suite has been run against the SIMH HP 21xx simulation.
@ -12,7 +12,7 @@ The test system configuration is the default SIMH configuration with these
alterations (except where noted in the individual diagnostic reports):
* All I/O devices are enabled.
* The CPU is configured as a 21MX with 128KW of memory.
* The CPU is configured as a 21MX-E with 128KW of memory.
Detailed diagnostic configuration, operation, and results are given after the
summary table. These may be used to duplicate the diagnostic results.
@ -42,9 +42,9 @@ The results of the diagnostic runs are summarized below:
101011 Extended Instruction Group (Index) 1432 3.2-3 Passed
101112 Extended Instruction Group (Word, Byte) 1728 3.2-3 Passed
101110 2100 Fast FORTRAN Package 1632 - No simulation
101213 M/E-Series Fast FORTRAN Package 1 1822 - No simulation
101115 M/E-Series Fast FORTRAN Package 2 1632 - No simulation
101110 2100 Fast FORTRAN Package 1632 3.4-0 Partial
101213 M/E-Series Fast FORTRAN Package 1 1822 3.4-0 Passed
101114 M/E-Series Fast FORTRAN Package 2 1632 3.4-0 Passed
101121 F-Series FPP/SIS/FFP 1926 - No simulation
102103 Memory Expansion Unit 1830 3.2-3 Passed
@ -492,7 +492,7 @@ TEST RESULT: Passed.
DSN 101011 - Extended Instruction Group (Index)
-----------------------------------------------
TESTED DEVICE: CPU (hp2100_cpu.c)
TESTED DEVICE: CPU (hp2100_cpu1.c)
CONFIGURATION: sim> deposit S 000000
sim> reset
@ -511,7 +511,7 @@ TEST RESULT: Passed.
DSN 101112 - Extended Instruction Group (Word, Byte, Bit)
---------------------------------------------------------
TESTED DEVICE: CPU (hp2100_cpu.c)
TESTED DEVICE: CPU (hp2100_cpu1.c)
CONFIGURATION: sim> set LPS diag
sim> deposit S 000014
@ -533,6 +533,148 @@ TEST RESULT: Passed.
--------------------------------------
DSN 101110 - 2100 Fast FORTRAN Package
--------------------------------------
TESTED DEVICE: CPU (hp2100_cpu1.c)
CONFIGURATION: sim> set CPU 2100
sim> set CPU 32K
sim> set CPU FFP
sim> deposit S 000013
sim> reset
sim> go 100
HALT instruction 102074
sim> deposit S 000000
sim> reset
sim> go
TEST REPORT: START 2100A-S FFP DIAGNOSTIC
H030 .GOTO TEST
H050 .ENTR TEST
H060 .ENTP TEST
H100 .SETP TEST
H110 ..MAP TEST
H120 SNGL TEST
H130 DBLE TEST
H140 .XADD TEST
TEST 07
E142 NOT INTERRUPTIBLE
HALT instruction 106042
sim> go
H150 .XSUB TEST
H160 .XMPY TEST
TEST 11
E162 NOT INTERRUPTIBLE
HALT instruction 106062
sim> go
H200 .XDIV TEST
H210 .DFER TEST
H220 .XFER TEST
PASS 000001
HALT instruction 102077
TEST RESULT: Partially passed.
TEST NOTES: Tests 07 and 11 test the interruptibility of the .XADD and .XMPY
instructions. These features are not simulated.
----------------------------------------------
DSN 101213 - M/E-Series Fast FORTRAN Package 1
----------------------------------------------
TESTED DEVICE: CPU (hp2100_cpu1.c)
CONFIGURATION: sim> set CPU FFP
sim> set LPS diag
sim> deposit S 000014
sim> reset
sim> go 100
HALT instruction 102074
sim> deposit S 000000
sim> reset
sim> go
TEST REPORT: START 21MX FFP DIAGNOSTIC 1
H110 ..MAP TEST
H120 SNGL TEST
H130 DBLE TEST
H210 .DFER TEST
H220 .XFER TEST
H230 PWR2 TEST
H240 .PACK TEST
H250 FLUN TEST
H260 .XPAK TEST
H300 .XCOM TEST
H310 ..DCM TEST
H320 DDINT TEST
H330 .CFER TEST
PASS 000001
HALT instruction 102077
TEST RESULT: Passed.
----------------------------------------------
DSN 101115 - M/E-Series Fast FORTRAN Package 2
----------------------------------------------
TESTED DEVICE: CPU (hp2100_cpu1.c)
CONFIGURATION: sim> set CPU FFP
sim> set LPS diag
sim> deposit S 000014
sim> reset
sim> go 100
HALT instruction 102074
sim> deposit S 000000
sim> reset
sim> go
TEST REPORT: START 21MX FFP DIAGNOSTIC 2
H030 .GOTO TEST
H050 .ENTR TEST
H060 .ENTP TEST
H100 .SETP TEST
H115 XADD TEST
H125 XSUB TEST
H135 XMPY TEST
H140 .XADD TEST
H150 .XSUB TEST
H160 .XMPY TEST
H200 .XDIV TEST
H215 XDIV TEST
PASS 000001
HALT instruction 102077
TEST RESULT: Passed.
----------------------------------
DSN 102103 - Memory Expansion Unit
----------------------------------
@ -933,7 +1075,7 @@ TEST REPORT: H0 7900/7901 CARTRIDGE DISC MEMORY DIAGNOSTIC
HALT instruction 102002
sim> detach DPC0
sim> set DPC0 unloaded
sim> go
H40 PROTECT U/D THEN READY UNIT 0
@ -942,7 +1084,7 @@ TEST REPORT: H0 7900/7901 CARTRIDGE DISC MEMORY DIAGNOSTIC
Simulation stopped
sim> set DPC0 locked
sim> attach DPC0 scratch.U0.7900.disc
sim> set DPC0 loaded
sim> go
H41 CLEAR U/D PROTECT,LOAD,PUSH RUN
@ -1113,7 +1255,7 @@ TEST REPORT: H66 SET FORMAT SWITCH ON UNIT 0,PUSH RUN
HALT instruction 102002
sim> set DS0 FORMAT
sim> set DS0 format
sim> go
H46 READ IN STEP 04
@ -1142,7 +1284,7 @@ TEST REPORT: H66 SET FORMAT SWITCH ON UNIT 0,PUSH RUN
HALT instruction 102002
sim> set DS0 NOFORMAT
sim> set DS0 noformat
sim> go
H46 READ IN STEP 07
@ -1171,7 +1313,7 @@ TEST REPORT: H66 SET FORMAT SWITCH ON UNIT 0,PUSH RUN
HALT instruction 102002
sim> set DS0 FORMAT
sim> set DS0 format
sim> go
H45 WRITE IN STEP 10
@ -1189,7 +1331,7 @@ TEST REPORT: H66 SET FORMAT SWITCH ON UNIT 0,PUSH RUN
HALT instruction 102002
sim> detach DS0
sim> set DS0 unloaded
sim> go
H107 READY UNIT 0
@ -1197,21 +1339,21 @@ TEST REPORT: H66 SET FORMAT SWITCH ON UNIT 0,PUSH RUN
[CTRL+E]
Simulation stopped
sim> attach DS0 scratch.U0.7905.disc
sim> set DS0 loaded
sim> go
H142 PROTECT U/D,PUSH RUN
HALT instruction 102002
sim> set DS0 LOCKED
sim> set DS0 locked
sim> go
H143 CLEAR U/D PROTECT,PUSH RUN
HALT instruction 102002
sim> set DS0 WRITEENABLED
sim> set DS0 writeenabled
sim> go
H110 PRESS PRESET(S),PRESS RUN
@ -1323,12 +1465,14 @@ TEST REPORT: H66 SET FORMAT SWITCH ON UNIT 0,PUSH RUN
sim> go
H46 READ IN STEP 43
E47 DATA WORD 0000 IS 156164 SHOULD BE 144300
E47 DATA WORD 0001 IS 023302 SHOULD BE 117306
E47 DATA WORD 0002 IS 114642 SHOULD BE 045322
H135 S P D TSTAT XXXX UNIT / E DRTYPE X A P F DF FS SC NR B
E64 STATUS IS 0 0 0 00111 0000 0000 / 0 000010 0 0 0 1 0 0 0 0 0
E64 STATUS IS 0 0 0 00000 0000 0000 / 0 000010 0 0 0 1 0 0 0 0 0
SHOULD BE 1 0 0 00000 XXXX XXXX / 0 000010 0 0 0 X 0 0 0 0 0
H137 TERMINATION STATUS IS "CYL CMP ERROR " SHOULD BE "NORMAL COMPLET"
E13 0000 WORDS TRANSFERRED 0128 EXPECTED
START 0016/00/33-LAST 0016/00/33 WORD COUNT 00128,OLD CYL 0016,UNIT 00
H137 TERMINATION STATUS IS "NORMAL COMPLET"
START 0016/00/33-LAST 0016/00/34 WORD COUNT 00128,OLD CYL 0016,UNIT 00
HALT instruction 102001
@ -1462,28 +1606,28 @@ TEST REPORT: 7970-13181 DIAG.
HALT instruction 106037
sim> attach MSC0 scratch.U0.7970.tape
sim> set MSC0 online
sim> go
H137 PUT TAPE UNIT ON-LINE
HALT instruction 106037
sim> attach MSC1 scratch.U1.7970.tape
sim> set MSC1 online
sim> go
H137 PUT TAPE UNIT ON-LINE
HALT instruction 106037
sim> attach MSC2 scratch.U2.7970.tape
sim> set MSC2 online
sim> go
H137 PUT TAPE UNIT ON-LINE
HALT instruction 106037
sim> attach MSC3 scratch.U3.7970.tape
sim> set MSC3 online
sim> go
PASS 000001
@ -1599,28 +1743,28 @@ TEST REPORT: 7970-13183 DIAG.
HALT instruction 106037
sim> attach MSC0 scratch.U0.7970.tape
sim> set MSC0 online
sim> go
H137 PUT TAPE UNIT ON-LINE
HALT instruction 106037
sim> attach MSC1 scratch.U1.7970.tape
sim> set MSC1 online
sim> go
H137 PUT TAPE UNIT ON-LINE
HALT instruction 106037
sim> attach MSC2 scratch.U2.7970.tape
sim> set MSC2 online
sim> go
H137 PUT TAPE UNIT ON-LINE
HALT instruction 106037
sim> attach MSC3 scratch.U3.7970.tape
sim> set MSC3 online
sim> go
PASS 000001
@ -2257,7 +2401,7 @@ TEST REPORT: H0 HP2100A CARTRIDGE DISC MEMORY DIAGNOSTIC
HALT instruction 102002
sim> detach DPC0
sim> set DPC0 unloaded
sim> go
H40 READY UNIT 0
@ -2265,7 +2409,7 @@ TEST REPORT: H0 HP2100A CARTRIDGE DISC MEMORY DIAGNOSTIC
[CTRL+E]
Simulation stopped
sim> attach DPC0 scratch.U0.2871.disc
sim> set DPC0 loaded
sim> go
H71 PRESS PRESET THEN PRESS RUN
@ -2446,7 +2590,7 @@ TEST REPORT: H66 SET FORMAT SWITCH ON UNIT 0,PUSH RUN
HALT instruction 102002
sim> detach DQC0
sim> set DQC0 unloaded
sim> go
H40 ENABLE UNIT 0
@ -2454,7 +2598,7 @@ TEST REPORT: H66 SET FORMAT SWITCH ON UNIT 0,PUSH RUN
[CTRL+E]
Simulation stopped
sim> attach DQC0 scratch.U0.2883.disc
sim> set DQC0 loaded
sim> go
H71 PRESS PRESET THEN PRESS RUN
@ -2497,7 +2641,7 @@ CONFIGURATION: sim> reset
HALT instruction 107001
sim> set DRC 180K
sim> set DRC TRACKPROT=8
sim> set DRC trackprot=8
sim> attach DRC0 scratch.U0.2770.disc
sim> deposit S 002611
sim> go
@ -2516,14 +2660,14 @@ TEST REPORT: H12 DEVICE HAS 90 SECTORS
HALT instruction 102002
sim> set DRC UNPROTECTED
sim> set DRC unprotected
sim> go
H10 SET TRACK PROTECT SWITCH TO PROTECTED,PRESS RUN
HALT instruction 102002
sim> set DRC PROTECTED
sim> set DRC protected
sim> go
H14 DEVICE HAS 0032 TRACKS,THE FOLLOWING ARE PROTECTED:
@ -2532,7 +2676,7 @@ TEST REPORT: H12 DEVICE HAS 90 SECTORS
HALT instruction 102002
sim> set DRC UNPROTECTED
sim> set DRC unprotected
sim> go
H36 PASS 0001
@ -2560,7 +2704,7 @@ CONFIGURATION: sim> reset
HALT instruction 107001
sim> set DRC 720K
sim> set DRC TRACKPROT=32
sim> set DRC trackprot=32
sim> attach DRC0 scratch.U0.2771.disc
sim> deposit S 002611
sim> go
@ -2579,14 +2723,14 @@ TEST REPORT: H12 DEVICE HAS 90 SECTORS
HALT instruction 102002
sim> set DRC UNPROTECTED
sim> set DRC unprotected
sim> go
H10 SET TRACK PROTECT SWITCH TO PROTECTED,PRESS RUN
HALT instruction 102002
sim> set DRC PROTECTED
sim> set DRC protected
sim> go
H14 DEVICE HAS 0128 TRACKS,THE FOLLOWING ARE PROTECTED:
@ -2595,7 +2739,7 @@ TEST REPORT: H12 DEVICE HAS 90 SECTORS
HALT instruction 102002
sim> set DRC UNPROTECTED
sim> set DRC unprotected
sim> go
H36 PASS 0001
@ -2623,7 +2767,7 @@ CONFIGURATION: sim> reset
HALT instruction 107001
sim> set DRC 384K
sim> set DRC TRACKPROT=16
sim> set DRC trackprot=16
sim> attach DRC0 scratch.U0.2773.disc
sim> deposit S 002611
sim> go
@ -2642,14 +2786,14 @@ TEST REPORT: H12 DEVICE HAS 32 SECTORS
HALT instruction 102002
sim> set DRC UNPROTECTED
sim> set DRC unprotected
sim> go
H10 SET TRACK PROTECT SWITCH TO PROTECTED,PRESS RUN
HALT instruction 102002
sim> set DRC PROTECTED
sim> set DRC protected
sim> go
H14 DEVICE HAS 0192 TRACKS,THE FOLLOWING ARE PROTECTED:
@ -2658,7 +2802,7 @@ TEST REPORT: H12 DEVICE HAS 32 SECTORS
HALT instruction 102002
sim> set DRC UNPROTECTED
sim> set DRC unprotected
sim> go
H36 PASS 0001
@ -2686,7 +2830,7 @@ CONFIGURATION: sim> reset
HALT instruction 107001
sim> set DRC 1536K
sim> set DRC TRACKPROT=64
sim> set DRC trackprot=64
sim> attach DRC0 scratch.U0.2775.disc
sim> deposit S 002611
sim> go
@ -2705,14 +2849,14 @@ TEST REPORT: H12 DEVICE HAS 32 SECTORS
HALT instruction 102002
sim> set DRC UNPROTECTED
sim> set DRC unprotected
sim> go
H10 SET TRACK PROTECT SWITCH TO PROTECTED,PRESS RUN
HALT instruction 102002
sim> set DRC PROTECTED
sim> set DRC protected
sim> go
H14 DEVICE HAS 0768 TRACKS,THE FOLLOWING ARE PROTECTED:
@ -2721,7 +2865,7 @@ TEST REPORT: H12 DEVICE HAS 32 SECTORS
HALT instruction 102002
sim> set DRC UNPROTECTED
sim> set DRC unprotected
sim> go
H36 PASS 0001

View file

@ -55,9 +55,11 @@ sim/ scp.h
sim/hp2100/ hp2100_cpu.h
hp2100_defs.h
hp2100_fp1.h
hp2100_cpu.c
hp2100_cpu1.c
hp2100_fp.c
hp2100_fp1.c
hp2100_dp.c
hp2100_dq.c
hp2100_dr.c
@ -78,9 +80,10 @@ The HP2100 simulator is configured as follows:
device simulates
name(s)
CPU 2116 CPU with 32KW memory
2100 CPU with 32KW memory, FP or IOP instructions
21MX-M/E CPU with 1024KW memory, FP, DMS, and/or IOP instructions
CPU 2116 CPU with up to 32KW of memory
2100 CPU with up to 32KW of memory
21MX-M or -E CPU with up to 1024KW of memory
EAU, FP, FFP, IOP, and/or DMS microcode extensions
MP 12892B memory protect
DMA0, DMA1 12895A/12897B direct memory access/dual channel port controller
PTR 12597A duplex register interface with 2748 paper tape reader
@ -110,13 +113,21 @@ The HP2100 simulator implements several unique stop conditions:
- more than INDMAX indirect references are detected during
memory reference address decoding
The HP2100 loader supports standard absolute binary format. The DUMP
The HP2100 LOAD command supports standard absolute binary format. The DUMP
command is not implemented.
2.1 CPU
CPU options include choice of instruction set and memory size. The
general command form is:
CPU options include choice of model, memory size, and instruction sets.
Several microcode options are simulated:
EAU Extended Arithmetic Unit
FP Single-Precision Floating Point
FFP Fast FORTRAN Processor
IOP 2000/Access I/O Processor
DMS Dynamic Mapping System
The general command form is:
SET {-F} CPU <option>
@ -132,6 +143,8 @@ Options that may be specified are:
SET CPU NOFP no FP instructions (2100 only)
SET CPU IOP IOP instructions (2100, 21MX only)
SET CPU NOIOP no IOP instructions (2100, 21MX only)
SET CPU FFP FFP instructions (2100, 21MX only)
SET CPU NOFFP no FFP instructions (2100, 21MX only)
SET CPU DMS DMS instructions (21MX only)
SET CPU NODMS no DMS instructions (21MX only)
SET CPU 4K set memory size = 4K
@ -144,11 +157,10 @@ Options that may be specified are:
SET CPU 512K set memory size = 512K (21MX only)
SET CPU 1024K set memory size = 1024K (21MX only)
On the 2100, EAU is standard, and the FP and IOP options are mutually
exclusive. On the 21MX, EAU and FP are standard. The 21MX optionally
includes DMS (dynamic mapping system) and IOP instructions. The 21MX-E
supports the TIMER instruction; on the 21MX-M, this instruction decodes
as MPY.
On the 2100, EAU is standard, and the FP or FFP and IOP options are mutually
exclusive. On the 21MX, EAU and FP are standard. The DMS, FFP, and IOP
instructions are optional. The 21MX-E supports the TIMER instruction; on
the 21MX-M, this instruction decodes as MPY.
Setting the CPU type to 2116, 2100, or 21MX establishes a consistent set
of common options. Additional SET CPU commands may follow to fine-tune
@ -813,6 +825,14 @@ Separate protection for the upper and lower platters of the 7900 drive
is not supported. Also, the drive Protect/Override switch is not
supported; drive protection is permanently overridden.
Drives may also have their heads unloaded and loaded:
SET DPCn UNLOADED unload heads on unit n
SET DPCn LOADED load heads on unit n
This provides a convenient method of setting a drive "down" without
detaching the associated disk image file.
The 12557A/13210A supports the BOOT command. BOOT DPC copies the IBL
for 7900 class disks into memory and starts it running. BOOT -R DPC
boots from the removable platter (head 0). The switch register (S) is
@ -869,7 +889,7 @@ Error handling is as follows:
error processed as
not attached disk not ready (drive unloaded)
not attached disk not ready (heads unloaded)
end of file assume rest of disk is zero
@ -887,6 +907,14 @@ Individual drives may be protected against writing:
SET DQCn LOCKED set unit n write locked
SET DQCn WRITEENABLED set unit n write enabled
Drives may also have their heads unloaded and loaded:
SET DQCn UNLOADED unload heads on unit n
SET DQCn LOADED load heads on unit n
This provides a convenient method of setting a drive "down" without
detaching the associated disk image file.
The 12565A supports the BOOT command. BOOT DQC copies the IBL for 2883
class disks into memory and starts it running. The switch register (S)
is set automatically to the value expected by the IBL loader:
@ -939,7 +967,7 @@ Error handling is as follows:
error processed as
not attached disk not ready
not attached disk not ready (heads unloaded)
end of file assume rest of disk is zero
@ -1052,6 +1080,14 @@ Separate protection for the upper and lower platters of the 7905 and
7906 drives is not supported. Protecting a 7905 or 7906 drive behaves
as though both of the Disc Protect switches were on.
Drives may also have their heads unloaded and loaded:
SET DSn UNLOADED unload heads on unit n
SET DSn LOADED load heads on unit n
This provides a convenient method of setting a drive "down" without
detaching the associated disk image file.
The setting of the drive Format switch may be changed with:
SET DSn FORMAT set format enabled
@ -1105,7 +1141,7 @@ Error handling is as follows:
error processed as
not attached disk not ready
not attached disk not ready (heads unloaded)
end of file assume rest of disk is zero
@ -1171,10 +1207,12 @@ Error handling is as follows:
2.7.2 13181A Magnetic Tape Controller (MSC, MSD) with Four 7970B Drives
18183A Magnetic Tape Controller (MSC, MSD) with Four 7970E Drives
Magnetic tape options include the ability to make the unit write enabled
or write locked, and the ability to select the 13181A (800 bpi) controller
or the 13183A (1600 bpi) controller.
Magnetic tape options include the ability to set a drive offline and
online, write enabled or write locked, and the ability to select the
13181A (800 bpi) controller or the 13183A (1600 bpi) controller.
SET MSCn OFFLINE set unit n offline
SET MSCn ONLINE set unit n online
SET MSCn LOCKED set unit n write locked
SET MSCn WRITEENABLED set unit n write enabled
SET MSC 13181A set controller to 13181A

View file

@ -26,6 +26,7 @@
dp 12557A 2871 disk subsystem
13210A 7900 disk subsystem
01-Mar-05 JDB Added SET UNLOAD/LOAD
07-Oct-04 JDB Fixed enable/disable from either device
Fixed ANY ERROR status for 12557A interface
Fixed unattached drive status for 12557A interface
@ -113,7 +114,9 @@
#include "hp2100_defs.h"
#define UNIT_V_WLK (UNIT_V_UF + 0) /* write locked */
#define UNIT_V_UNLOAD (UNIT_V_UF + 1) /* heads unloaded */
#define UNIT_WLK (1 << UNIT_V_WLK)
#define UNIT_UNLOAD (1 << UNIT_V_UNLOAD)
#define FNC u3 /* saved function */
#define DRV u4 /* drive number (DC) */
#define UNIT_WPRT (UNIT_WLK | UNIT_RO) /* write prot */
@ -231,11 +234,12 @@ int32 dpcio (int32 inst, int32 IR, int32 dat);
t_stat dpc_svc (UNIT *uptr);
t_stat dpd_svc (UNIT *uptr);
t_stat dpc_reset (DEVICE *dptr);
t_stat dpc_vlock (UNIT *uptr, int32 val);
t_stat dpc_attach (UNIT *uptr, char *cptr);
t_stat dpc_detach (UNIT* uptr);
t_stat dpc_boot (int32 unitno, DEVICE *dptr);
void dp_god (int32 fnc, int32 drv, int32 time);
void dp_goc (int32 fnc, int32 drv, int32 time);
t_stat dpc_load_unload (UNIT *uptr, int32 value, char *cptr, void *desc);
t_stat dp_settype (UNIT *uptr, int32 val, char *cptr, void *desc);
t_stat dp_showtype (FILE *st, UNIT *uptr, int32 val, void *desc);
@ -291,14 +295,14 @@ DEVICE dpd_dev = {
*/
UNIT dpc_unit[] = {
{ UDATA (&dpc_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
UNIT_ROABLE, DP_SIZE3) },
{ UDATA (&dpc_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
UNIT_ROABLE, DP_SIZE3) },
{ UDATA (&dpc_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
UNIT_ROABLE, DP_SIZE3) },
{ UDATA (&dpc_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
UNIT_ROABLE, DP_SIZE3) } };
{ UDATA (&dpc_svc, UNIT_FIX | UNIT_ATTABLE | UNIT_ROABLE |
UNIT_DISABLE | UNIT_UNLOAD, DP_SIZE3) },
{ UDATA (&dpc_svc, UNIT_FIX | UNIT_ATTABLE | UNIT_ROABLE |
UNIT_DISABLE | UNIT_UNLOAD, DP_SIZE3) },
{ UDATA (&dpc_svc, UNIT_FIX | UNIT_ATTABLE | UNIT_ROABLE |
UNIT_DISABLE | UNIT_UNLOAD, DP_SIZE3) },
{ UDATA (&dpc_svc, UNIT_FIX | UNIT_ATTABLE | UNIT_ROABLE |
UNIT_DISABLE | UNIT_UNLOAD, DP_SIZE3) } };
REG dpc_reg[] = {
{ ORDATA (OBUF, dpc_obuf, 16) },
@ -329,6 +333,8 @@ REG dpc_reg[] = {
{ NULL } };
MTAB dpc_mod[] = {
{ UNIT_UNLOAD, UNIT_UNLOAD, "heads unloaded", "UNLOADED", dpc_load_unload },
{ UNIT_UNLOAD, 0, "heads loaded", "LOADED", dpc_load_unload },
{ UNIT_WLK, 0, "write enabled", "WRITEENABLED", NULL },
{ UNIT_WLK, UNIT_WLK, "write locked", "LOCKED", NULL },
{ MTAB_XTD | MTAB_VDV, 1, NULL, "13210A",
@ -345,7 +351,7 @@ DEVICE dpc_dev = {
"DPC", dpc_unit, dpc_reg, dpc_mod,
DP_NUMDRV, 8, 24, 1, 8, 16,
NULL, NULL, &dpc_reset,
&dpc_boot, &dpc_attach, NULL,
&dpc_boot, &dpc_attach, &dpc_detach,
&dpc_dib, DEV_DISABLE };
/* IOT routines */
@ -561,7 +567,7 @@ case FNC_SEEK1: /* seek, need hd/sec */
case FNC_STA: /* read status */
if (CMD (devd) || dp_ctype) { /* dch act or 13210? */
if (dpc_unit[drv].flags & UNIT_ATT) { /* attached? */
if ((dpc_unit[drv].flags & UNIT_UNLOAD) == 0) { /* drive up? */
dpd_ibuf = dpc_sta[drv] & ~STA_ERR; /* clear err */
if (dp_ctype) dpd_ibuf = /* 13210? */
(dpd_ibuf & ~(STA_MBZ13 | STA_PROT)) |
@ -621,7 +627,7 @@ err = 0; /* assume no err */
drv = uptr - dpc_dev.units; /* get drive no */
devc = dpc_dib.devno; /* get cch devno */
devd = dpd_dib.devno; /* get dch devno */
if ((uptr->flags & UNIT_ATT) == 0) { /* not attached? */
if (uptr->flags & UNIT_UNLOAD) { /* drive down? */
setFSR (devc); /* set cch flg */
clrCMD (devc); /* clr cch cmd */
dpc_sta[drv] = 0; /* clr status */
@ -760,20 +766,42 @@ return SCPE_OK;
t_stat dpc_attach (UNIT *uptr, char *cptr)
{
int32 drv;
t_stat r;
drv = uptr - dpc_dev.units; /* get drive no */
r = attach_unit (uptr, cptr); /* attach unit */
if (r != SCPE_OK) return r;
dpc_sta[drv] = dpc_sta[drv] | STA_ATN | STA_1ST; /* update status */
if (dpc_poll) { /* polling enabled? */
dpc_dib.fbf = 1; /* set fbf */
dpc_dib.flg = 1; /* set flg */
dpc_dib.srq = 1; } /* srq follows flg */
if (r == SCPE_OK) dpc_load_unload (uptr, 0, NULL, NULL);/* if OK, load heads */
return r;
}
/* Detach routine */
t_stat dpc_detach (UNIT* uptr)
{
dpc_load_unload (uptr, UNIT_UNLOAD, NULL, NULL); /* unload heads */
return detach_unit (uptr); /* detach unit */
}
/* Load and unload heads */
t_stat dpc_load_unload (UNIT *uptr, int32 value, char *cptr, void *desc)
{
uint32 drv;
if ((uptr->flags & UNIT_ATT) == 0) return SCPE_UNATT; /* must be attached to load */
if (value == UNIT_UNLOAD) /* unload heads? */
uptr->flags = uptr->flags | UNIT_UNLOAD; /* indicate unload */
else { /* load heads */
uptr->flags = uptr->flags & ~UNIT_UNLOAD; /* indicate load */
drv = uptr - dpc_dev.units; /* get drive no */
dpc_sta[drv] = dpc_sta[drv] | STA_ATN | STA_1ST;/* update status */
if (dpc_poll) { /* polling enabled? */
dpc_dib.fbf = 1; /* set fbf */
dpc_dib.flg = 1; /* set flg */
dpc_dib.srq = 1; } } /* srq follows flg */
return SCPE_OK;
}
/* Set controller type */
t_stat dp_settype (UNIT *uptr, int32 val, char *cptr, void *desc)

View file

@ -25,6 +25,7 @@
dq 12565A 2883 disk system
01-Mar-05 JDB Added SET UNLOAD/LOAD
07-Oct-04 JDB Fixed enable/disable from either device
Shortened xtime from 5 to 3 (drive avg 156KW/second)
Fixed not ready/any error status
@ -71,7 +72,9 @@
#include "hp2100_defs.h"
#define UNIT_V_WLK (UNIT_V_UF + 0) /* write locked */
#define UNIT_V_UNLOAD (UNIT_V_UF + 1) /* heads unloaded */
#define UNIT_WLK (1 << UNIT_V_WLK)
#define UNIT_UNLOAD (1 << UNIT_V_UNLOAD)
#define FNC u3 /* saved function */
#define DRV u4 /* drive number (DC) */
#define UNIT_WPRT (UNIT_WLK | UNIT_RO) /* write prot */
@ -166,6 +169,9 @@ int32 dqcio (int32 inst, int32 IR, int32 dat);
t_stat dqc_svc (UNIT *uptr);
t_stat dqd_svc (UNIT *uptr);
t_stat dqc_reset (DEVICE *dptr);
t_stat dqc_attach (UNIT *uptr, char *cptr);
t_stat dqc_detach (UNIT* uptr);
t_stat dqc_load_unload (UNIT *uptr, int32 value, char *cptr, void *desc);
t_stat dqc_boot (int32 unitno, DEVICE *dptr);
void dq_god (int32 fnc, int32 drv, int32 time);
void dq_goc (int32 fnc, int32 drv, int32 time);
@ -222,10 +228,10 @@ DEVICE dqd_dev = {
*/
UNIT dqc_unit[] = {
{ UDATA (&dqc_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
UNIT_ROABLE, DQ_SIZE) },
{ UDATA (&dqc_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
UNIT_ROABLE, DQ_SIZE) } };
{ UDATA (&dqc_svc, UNIT_FIX | UNIT_ATTABLE | UNIT_ROABLE |
UNIT_DISABLE | UNIT_UNLOAD, DQ_SIZE) },
{ UDATA (&dqc_svc, UNIT_FIX | UNIT_ATTABLE | UNIT_ROABLE |
UNIT_DISABLE | UNIT_UNLOAD, DQ_SIZE) } };
REG dqc_reg[] = {
{ ORDATA (OBUF, dqc_obuf, 16) },
@ -252,6 +258,8 @@ REG dqc_reg[] = {
{ NULL } };
MTAB dqc_mod[] = {
{ UNIT_UNLOAD, UNIT_UNLOAD, "heads unloaded", "UNLOADED", dqc_load_unload },
{ UNIT_UNLOAD, 0, "heads loaded", "LOADED", dqc_load_unload },
{ UNIT_WLK, 0, "write enabled", "WRITEENABLED", NULL },
{ UNIT_WLK, UNIT_WLK, "write locked", "LOCKED", NULL },
{ MTAB_XTD | MTAB_VDV, 1, "DEVNO", "DEVNO",
@ -262,7 +270,7 @@ DEVICE dqc_dev = {
"DQC", dqc_unit, dqc_reg, dqc_mod,
DQ_NUMDRV, 8, 24, 1, 8, 16,
NULL, NULL, &dqc_reset,
&dqc_boot, NULL, NULL,
&dqc_boot, &dqc_attach, &dqc_detach,
&dqc_dib, DEV_DISABLE };
/* IOT routines */
@ -472,7 +480,7 @@ case FNC_RCL: /* recalibrate */
case FNC_STA: /* read status */
if (CMD (devd)) { /* dch active? */
if (dqc_unit[drv].flags & UNIT_ATT) /* attached? */
if ((dqc_unit[drv].flags & UNIT_UNLOAD) == 0) /* drive up? */
dqd_ibuf = dqc_sta[drv] & ~STA_DID;
else dqd_ibuf = STA_NRDY;
if (dqd_ibuf & STA_ANYERR) /* errors? set flg */
@ -527,7 +535,7 @@ err = 0; /* assume no err */
drv = uptr - dqc_dev.units; /* get drive no */
devc = dqc_dib.devno; /* get cch devno */
devd = dqd_dib.devno; /* get dch devno */
if ((uptr->flags & UNIT_ATT) == 0) { /* not attached? */
if (uptr->flags & UNIT_UNLOAD) { /* drive down? */
setFSR (devc); /* set cch flg */
clrCMD (devc); /* clr cch cmd */
dqc_sta[drv] = 0; /* clr status */
@ -671,11 +679,33 @@ for (drv = 0; drv < DQ_NUMDRV; drv++) { /* loop thru drives */
return SCPE_OK;
}
/* Write lock/enable routine */
/* Attach routine */
t_stat dqc_vlock (UNIT *uptr, int32 val)
t_stat dqc_attach (UNIT *uptr, char *cptr)
{
if (uptr->flags & UNIT_ATT) return SCPE_ARG;
t_stat r;
r = attach_unit (uptr, cptr); /* attach unit */
if (r == SCPE_OK) dqc_load_unload (uptr, 0, NULL, NULL);/* if OK, load heads */
return r;
}
/* Detach routine */
t_stat dqc_detach (UNIT* uptr)
{
dqc_load_unload (uptr, UNIT_UNLOAD, NULL, NULL); /* unload heads */
return detach_unit (uptr); /* detach unit */
}
/* Load and unload heads */
t_stat dqc_load_unload (UNIT *uptr, int32 value, char *cptr, void *desc)
{
if ((uptr->flags & UNIT_ATT) == 0) return SCPE_UNATT; /* must be attached to load */
if (value == UNIT_UNLOAD) /* unload heads? */
uptr->flags = uptr->flags | UNIT_UNLOAD; /* indicate unload */
else uptr->flags = uptr->flags & ~UNIT_UNLOAD; /* indicate load */
return SCPE_OK;
}

View file

@ -1,6 +1,6 @@
/* hp2100_ds.c: HP 2100 13037 disk controller simulator
Copyright (c) 2004, Robert M. Supnik
Copyright (c) 2004-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"),
@ -25,6 +25,9 @@
ds 13037 disk controller
18-Mar-05 RMS Added attached test to detach routine
01-Mar-05 JDB Added SET UNLOAD/LOAD
States of the controller: the controller uP runs all the time, but most of
the time it is waiting for an event. The simulator only 'runs' the controller
when there's an event to process: change in CPU interface state, change in
@ -77,14 +80,16 @@
/* Flags in the unit flags word */
#define UNIT_V_WLK (UNIT_V_UF + 0) /* write locked */
#define UNIT_V_FMT (UNIT_V_UF + 1) /* format enabled */
#define UNIT_V_UNLOAD (UNIT_V_UF + 1) /* heads unloaded */
#define UNIT_V_DTYPE (UNIT_V_UF + 2) /* disk type */
#define UNIT_M_DTYPE 3
#define UNIT_V_AUTO (UNIT_V_UF + 4) /* autosize */
#define UNIT_V_FMT (UNIT_V_UF + 5) /* format enabled */
#define UNIT_WLK (1 << UNIT_V_WLK)
#define UNIT_FMT (1 << UNIT_V_FMT)
#define UNIT_DTYPE (UNIT_M_DTYPE << UNIT_V_DTYPE)
#define UNIT_AUTO (1 << UNIT_V_AUTO)
#define UNIT_UNLOAD (1 << UNIT_V_UNLOAD)
#define GET_DTYPE(x) (((x) >> UNIT_V_DTYPE) & UNIT_M_DTYPE)
#define UNIT_WPR (UNIT_WLK | UNIT_RO) /* write prot */
@ -406,6 +411,7 @@ t_stat ds_reset (DEVICE *dptr);
t_stat ds_attach (UNIT *uptr, char *cptr);
t_stat ds_detach (UNIT *uptr);
t_stat ds_boot (int32 unitno, DEVICE *dptr);
t_stat ds_load_unload (UNIT *uptr, int32 value, char *cptr, void *desc);
t_stat ds_set_size (UNIT *uptr, int32 val, char *cptr, void *desc);
void ds_poll (void);
void ds_docmd (uint32 cmd);
@ -443,22 +449,22 @@ void ds_fifo_reset (void);
DIB ds_dib = { DS, 0, 0, 0, 0, 0, &dsio };
UNIT ds_unit[] = {
{ UDATA (&ds_svc_u, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
UNIT_ROABLE, D7905_SIZE) },
{ UDATA (&ds_svc_u, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
UNIT_ROABLE, D7905_SIZE) },
{ UDATA (&ds_svc_u, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
UNIT_ROABLE, D7905_SIZE) },
{ UDATA (&ds_svc_u, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
UNIT_ROABLE, D7905_SIZE) },
{ UDATA (&ds_svc_u, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
UNIT_ROABLE, D7905_SIZE) },
{ UDATA (&ds_svc_u, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
UNIT_ROABLE, D7905_SIZE) },
{ UDATA (&ds_svc_u, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
UNIT_ROABLE, D7905_SIZE) },
{ UDATA (&ds_svc_u, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
UNIT_ROABLE, D7905_SIZE) },
{ UDATA (&ds_svc_u, UNIT_FIX | UNIT_ATTABLE | UNIT_ROABLE |
UNIT_DISABLE | UNIT_UNLOAD, D7905_SIZE) },
{ UDATA (&ds_svc_u, UNIT_FIX | UNIT_ATTABLE | UNIT_ROABLE |
UNIT_DISABLE | UNIT_UNLOAD, D7905_SIZE) },
{ UDATA (&ds_svc_u, UNIT_FIX | UNIT_ATTABLE | UNIT_ROABLE |
UNIT_DISABLE | UNIT_UNLOAD, D7905_SIZE) },
{ UDATA (&ds_svc_u, UNIT_FIX | UNIT_ATTABLE | UNIT_ROABLE |
UNIT_DISABLE | UNIT_UNLOAD, D7905_SIZE) },
{ UDATA (&ds_svc_u, UNIT_FIX | UNIT_ATTABLE | UNIT_ROABLE |
UNIT_DISABLE | UNIT_UNLOAD, D7905_SIZE) },
{ UDATA (&ds_svc_u, UNIT_FIX | UNIT_ATTABLE | UNIT_ROABLE |
UNIT_DISABLE | UNIT_UNLOAD, D7905_SIZE) },
{ UDATA (&ds_svc_u, UNIT_FIX | UNIT_ATTABLE | UNIT_ROABLE |
UNIT_DISABLE | UNIT_UNLOAD, D7905_SIZE) },
{ UDATA (&ds_svc_u, UNIT_FIX | UNIT_ATTABLE | UNIT_ROABLE |
UNIT_DISABLE | UNIT_UNLOAD, D7905_SIZE) },
{ UDATA (&ds_svc_c, UNIT_DIS, 0) },
{ UDATA (&ds_svc_t, UNIT_DIS, 0) } };
@ -504,6 +510,8 @@ REG ds_reg[] = {
{ NULL } };
MTAB ds_mod[] = {
{ UNIT_UNLOAD, UNIT_UNLOAD, "heads unloaded", "UNLOADED", ds_load_unload },
{ UNIT_UNLOAD, 0, "heads loaded", "LOADED", ds_load_unload },
{ UNIT_WLK, 0, "write enabled", "WRITEENABLED", NULL },
{ UNIT_WLK, UNIT_WLK, "write locked", "LOCKED", NULL },
{ UNIT_FMT, 0, "format disabled", "NOFORMAT", NULL },
@ -850,7 +858,7 @@ switch (op) { /* case on function */
/* Seek and recalibrate */
case DSC_RECAL: /* recalibrate */
if (uptr->flags & UNIT_ATT) { /* attached? */
if ((uptr->flags & UNIT_UNLOAD) == 0) { /* drive up? */
ds_start_seek (uptr, 0, DSC_RECAL|DSC_2ND); /* set up seek */
ds_set_idle (); /* ctrl is idle */
}
@ -873,7 +881,7 @@ case DSC_SEEK | DSC_2ND: /* waiting for word 1 */
case DSC_SEEK | DSC_3RD: /* waiting for word 2 */
if (!DS_FIFO_EMPTY) { /* OTA ds? */
ds_hs = ds_fifo_read (); /* save head/sector */
if (uptr->flags & UNIT_ATT) { /* attached? */
if ((uptr->flags & UNIT_UNLOAD) == 0) { /* drive up? */
ds_start_seek (uptr, ds_cyl, DSC_SEEK|DSC_4TH); /* set up seek */
ds_set_idle (); /* ctrl is idle */
}
@ -900,7 +908,7 @@ case DSC_ROFF | DSC_2ND: /* poll done */
break;
case DSC_COLD: /* cold load read */
if (uptr->flags & UNIT_ATT) /* attached? */
if ((uptr->flags & UNIT_UNLOAD) == 0) /* drive up? */
ds_start_seek (uptr, 0, DSC_READ); /* set up seek */
else ds_cmd_done (1, DS1_S2ERR); /* no, not ready error */
break;
@ -1065,7 +1073,7 @@ sta = drv_tab[dtyp].id | /* form status */
uptr->STA | /* static bits */
((uptr->flags & UNIT_WPR)? DS2_RO: 0) | /* dynamic bits */
((uptr->flags & UNIT_FMT)? DS2_FRM: 0) |
((uptr->flags & UNIT_ATT)? 0: DS2_NR | DS2_BS) |
((uptr->flags & UNIT_UNLOAD)? DS2_NR | DS2_BS: 0) |
(sim_is_active (uptr)? DS2_BS: 0);
if (sta & DS2_ALLERR) sta = sta | DS2_ERR; /* set error */
return sta;
@ -1133,7 +1141,7 @@ uint32 dtyp = GET_DTYPE (uptr->flags);
ds_eod = 0; /* init eod */
ds_ptr = 0; /* init buffer ptr */
if ((uptr->flags & UNIT_ATT) == 0) { /* not attached? */
if (uptr->flags & UNIT_UNLOAD) { /* drive down? */
ds_cmd_done (1, DS1_S2ERR);
return TRUE;
}
@ -1410,7 +1418,7 @@ t_stat r;
uptr->capac = drv_tab[GET_DTYPE (uptr->flags)].size;
r = attach_unit (uptr, cptr); /* attach unit */
if (r != SCPE_OK) return r; /* error? */
uptr->STA = DS2_ATN | DS2_FS; /* update drive status */
ds_load_unload (uptr, 0, NULL, NULL); /* if OK, load heads */
ds_sched_atn (uptr); /* schedule attention */
if (((uptr->flags & UNIT_AUTO) == 0) || /* static size? */
((p = sim_fsize (uptr->fileref)) == 0)) return SCPE_OK; /* new file? */
@ -1428,11 +1436,26 @@ return SCPE_OK;
t_stat ds_detach (UNIT *uptr)
{
uptr->STA = DS2_ATN; /* update drive status */
ds_sched_atn (uptr); /* schedule attention */
if (!(uptr->flags & UNIT_ATT)) return SCPE_OK; /* attached? */
ds_load_unload (uptr, UNIT_UNLOAD, NULL, NULL); /* unload heads */
return detach_unit (uptr);
}
/* Load and unload heads */
t_stat ds_load_unload (UNIT *uptr, int32 value, char *cptr, void *desc)
{
if ((uptr->flags & UNIT_ATT) == 0) return SCPE_UNATT; /* must be attached to [un]load */
if (value == UNIT_UNLOAD) { /* unload heads? */
uptr->flags = uptr->flags | UNIT_UNLOAD; /* indicate unload */
uptr->STA = DS2_ATN; /* update drive status */
ds_sched_atn (uptr); } /* schedule attention */
else { /* load heads */
uptr->flags = uptr->flags & ~UNIT_UNLOAD; /* indicate load */
uptr->STA = DS2_ATN | DS2_FS; } /* update drive status */
return SCPE_OK;
}
/* Schedule attention interrupt if CTL set, not restore, and controller idle */
void ds_sched_atn (UNIT *uptr)

View file

@ -23,6 +23,7 @@
be used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from Robert M Supnik.
25-Feb-05 JDB Added FFP helpers f_pack, f_unpack, f_pwr2
11-Feb-05 JDB Fixed missing negative overflow renorm in StoreFP
26-Dec-04 RMS Separated A/B from M[0/1] for DMA IO (from Dave Bryan)
15-Jul-03 RMS Fixed signed/unsigned warning
@ -105,6 +106,7 @@ struct ufp { /* unpacked fp */
#define FR_NEG(v) ((~(v) + 1) & DMASK32)
extern uint16 ABREG[2];
uint32 UnpackFP (struct ufp *fop, uint32 opnd);
void NegFP (struct ufp *fop);
void NormFP (struct ufp *fop);
@ -260,6 +262,46 @@ if (fop1.fr) { /* dvd != 0? */
return StoreFP (&quo); /* store result */
}
/* Fast FORTRAN Processor helpers. */
/* Pack mantissa in A/B and exponent and return fp in A/B */
uint32 f_pack (int32 expon)
{
struct ufp fop;
fop.fr = FPAB;
fop.exp = expon;
return StoreFP (&fop);
}
/* Unpack fp number in A/B into A (exponent) and B (lower mantissa) */
void f_unpack (void)
{
AR = FP_GETEXP (BR); /* get exponent */
if (FP_GETEXPS (BR)) AR = (AR | ~FP_M_EXP) & DMASK; /* < 0? sext */
BR = BR & (uint16) ~(FP_EXP | FP_EXPS); /* clear exp */
return;
}
/* Multiply fp number in A/B by 2**n and return in A/B.
Exponent overflow or underflow wraps around. */
void f_pwr2 (int32 n)
{
uint32 save_a;
if (AR | BR) { /* microcode test */
save_a = AR;
f_unpack (); /* unpack exponent */
AR = AR + n; /* multiply */
BR = BR | ((AR & FP_M_EXP) << FP_V_EXP) | /* merge exponent */
((AR & SIGN)? (1 << FP_V_EXPS): 0); /* and exponent sign */
AR = save_a; }
return;
}
/* Utility routines */
/* Unpack operand */

508
HP2100/hp2100_fp1.c Normal file
View file

@ -0,0 +1,508 @@
/* hp2100_fp1.c: HP 2100/21MX extended-precision floating point routines
Copyright (c) 2005, J. David Bryan
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 the author shall not
be used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from the author.
Primary references:
- HP 1000 M/E/F-Series Computers Technical Reference Handbook
(5955-0282, Mar-1980)
- DOS/RTE Relocatable Library Reference Manual
(24998-90001, Oct-1981)
The extended-precision floating-point format is a 48-bit extension of the
32-bit format used for single precision. A packed "XP" number consists of a
40-bit twos-complement mantissa and an 8-bit twos-complement exponent. The
exponent is rotated left so that the sign is in the LSB. Pictorially, an XP
number appears in memory as follows:
15 14 0
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|S | mantissa high | : M
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| mantissa middle | : M + 1
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| mantissa low | exponent |XS| : M + 2
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
15 8 7 1 0
In a normalized value, the sign and MSB of the mantissa differ. Zero is
represented by all three words = 0.
Internally, an unpacked XP number is contained in a structure having a signed
64-bit mantissa and a signed 32-bit exponent. The mantissa is masked to 48
bits and left-justified, while the exponent is right-justified.
*/
#include "hp2100_defs.h"
#include "hp2100_cpu.h"
#include "hp2100_fp1.h"
#if defined (HAVE_INT64) /* we need int64 support */
/* packed starting bit numbers */
#define XP_PAD 16 /* padding LSBs */
#define XP_V_MSIGN (47 + XP_PAD) /* mantissa sign */
#define XP_V_MANT ( 8 + XP_PAD) /* mantissa */
#define XP_V_EXP ( 1 + XP_PAD) /* exponent */
#define XP_V_ESIGN ( 0 + XP_PAD) /* exponent sign */
/* packed bit widths */
#define XP_W_MSIGN 1 /* mantissa sign */
#define XP_W_MANT 39 /* mantissa */
#define XP_W_EXP 7 /* exponent */
#define XP_W_ESIGN 1 /* exponent sign */
/* packed bit masks */
#define XP_M_MSIGN (((t_uint64) 1 << XP_W_MSIGN) - 1) /* mantissa sign */
#define XP_M_MANT (((t_uint64) 1 << XP_W_MANT) - 1) /* mantissa */
#define XP_M_EXP (((t_uint64) 1 << XP_W_EXP) - 1) /* exponent */
#define XP_M_ESIGN (((t_uint64) 1 << XP_W_ESIGN) - 1) /* exponent sign */
/* packed field masks */
#define XP_MSIGN (XP_M_MSIGN << XP_V_MSIGN) /* mantissa sign */
#define XP_MANT (XP_M_MANT << XP_V_MANT) /* mantissa */
#define XP_SMANT (XP_MSIGN | XP_MANT) /* signed mantissa */
/* unpacked starting bit numbers */
#define XP_V_UMANT (0 + XP_PAD) /* signed mantissa */
/* unpacked bit widths */
#define XP_W_USMANT 48 /* signed mantissa */
/* unpacked bit masks */
#define XP_M_USMANT (((t_uint64) 1 << XP_W_USMANT) - 1) /* mantissa */
/* unpacked field masks */
#define XP_USMANT (XP_M_USMANT << XP_V_UMANT) /* signed mantissa */
/* values */
#define XP_ONEHALF ((t_int64) 1 << (XP_V_MSIGN - 1)) /* mantissa = 0.5 */
#define XP_HALSBPOS ((t_int64) 1 << (XP_V_MANT - 1)) /* + 1/2 LSB */
#define XP_HALSBNEG ((t_int64) XP_HALSBPOS - 1) /* - 1/2 LSB */
#define XP_MAXPOS ((t_int64) XP_MANT) /* maximum pos mantissa */
#define XP_MAXNEG ((t_int64) XP_MSIGN) /* maximum neg mantissa */
#define XP_MAXEXP ((t_int64) XP_M_EXP) /* maximum pos exponent */
/* helpers */
#define DENORM(x) ((((x) ^ (x) << 1) & XP_MSIGN) == 0)
#define TO_INT64(xpn) ((t_int64) ((t_uint64) (xpn).high << 32 | (xpn).low))
/* internal unpacked extended-precision representation */
typedef struct { t_int64 mantissa;
int32 exponent; } XPU;
/* Private routines */
/* Pack an unpacked mantissa and exponent */
static XPN to_xpn (t_uint64 m, int32 e)
{
XPN packed;
packed.high = (uint32) (m >> 32);
packed.low = (uint32) (m | ((e & XP_M_EXP) << XP_V_EXP) | ((e < 0) << XP_V_ESIGN));
return packed;
}
/* Unpack a packed number */
static XPU unpack (XPN packed)
{
XPU unpacked;
unpacked.mantissa = TO_INT64 (packed) & XP_SMANT; /* left-justify mantissa */
unpacked.exponent = (int8) ((packed.low >> XP_V_EXP & XP_M_EXP) | /* sign-extend exponent */
packed.low >> (XP_V_ESIGN - XP_W_EXP));
return unpacked;
}
/* Normalize an unpacked number */
static void normalize (XPU *unpacked)
{
if (unpacked->mantissa) { /* non-zero? */
while (DENORM (unpacked->mantissa)) { /* normal form? */
unpacked->exponent = unpacked->exponent - 1; /* no, so shift */
unpacked->mantissa = unpacked->mantissa << 1; } }
else unpacked->exponent = 0; /* clean for zero */
return;
}
/* Round and pack an unpacked number */
static uint32 pack (XPN *packed, XPU unpacked)
{
int32 sign, overflow = 0;
normalize (&unpacked); /* normalize */
sign = (unpacked.mantissa < 0); /* save sign */
unpacked.mantissa = (unpacked.mantissa + /* round the number */
(sign? XP_HALSBNEG: XP_HALSBPOS)) & XP_SMANT; /* mask off rounding bits */
if (sign != (unpacked.mantissa < 0)) { /* pos overflow? */
unpacked.mantissa = /* renormalize */
(t_uint64) unpacked.mantissa >> 1 & XP_SMANT; /* and remask */
unpacked.exponent = unpacked.exponent + 1; }
else normalize (&unpacked); /* neg overflow? renorm */
unpacked.mantissa = unpacked.mantissa & XP_SMANT;
if (unpacked.mantissa == 0) /* result 0? */
packed->high = packed->low = 0; /* return 0 */
else if (unpacked.exponent < -(XP_MAXEXP + 1)) { /* underflow? */
packed->high = packed->low = 0; /* return 0 */
overflow = 1; } /* and set overflow */
else if (unpacked.exponent > XP_MAXEXP) { /* overflow? */
if (sign) *packed = to_xpn (XP_MAXNEG, XP_MAXEXP); /* return neg infinity */
else *packed = to_xpn (XP_MAXPOS, XP_MAXEXP); /* or pos infinity */
overflow = 1; } /* with overflow */
else *packed = to_xpn (unpacked.mantissa, unpacked.exponent);
return overflow;
}
/* Complement an unpacked number */
static void complement (XPU *result)
{
result->mantissa = -result->mantissa; /* negate mantissa */
if (result->mantissa == XP_MAXNEG) { /* maximum negative? */
result->mantissa = (t_uint64) result->mantissa >> 1; /* renormalize to pos */
result->exponent = result->exponent + 1; } /* correct exponent */
return;
}
/* Add two unpacked numbers
The mantissas are first aligned (if necessary) by scaling the smaller of the
two operands. If the magnitude of the difference between the exponents is
greater than the number of significant bits, then the smaller number has been
scaled to zero, and so the sum is simply the larger operand. Otherwise, the
sum is computed and checked for overflow, which has occured if the signs of
the operands are the same but differ from that of the result. Scaling and
renormalization is perfomed if overflow occurred. */
static void add (XPU *sum, XPU augend, XPU addend)
{
int32 magn;
if (augend.mantissa == 0) *sum = addend; /* x + 0 = x */
else if (addend.mantissa == 0) *sum = augend; /* 0 + x = x */
else {
magn = augend.exponent - addend.exponent; /* difference exponents */
if (magn > 0) { /* addend smaller? */
*sum = augend; /* preset augend */
addend.mantissa = addend.mantissa >> magn; } /* align addend */
else { /* augend smaller? */
*sum = addend; /* preset addend */
magn = -magn; /* make difference positive */
augend.mantissa = augend.mantissa >> magn; } /* align augend */
if (magn <= XP_W_MANT + 1) { /* check mangitude */
sum->mantissa = addend.mantissa + augend.mantissa; /* add mantissas */
if (((addend.mantissa < 0) == (augend.mantissa < 0)) && /* chk overflow */
((addend.mantissa < 0) != (sum->mantissa < 0))) {
sum->mantissa = (addend.mantissa & XP_MSIGN) | /* restore sign */
(t_uint64) sum->mantissa >> 1; /* renormalize */
sum->exponent = sum->exponent + 1; } } } /* adjust exponent */
return;
}
/* Multiply two unpacked numbers
The firmware first negates the operands as necessary so that the values are
positive. Then it performs six of the nine 16-bit x 16-bit = 32-bit unsigned
multiplications required for a full 96-bit product. Given a 48-bit
multiplicand "a1a2a3" and a 48-bit multiplier "b1b2b3", the firmware performs
these calculations to develop a 48-bit product:
a1 a2 a3
+-------+-------+-------+
b1 b2 b3
+-------+-------+-------+
_________________________
a1 * b3 [m1]
+-------+-------+
a2 * b2 [m2]
+-------+-------+
a1 * b2 [m3]
+-------+-------+
a3 * b1 [m4]
+-------+-------+
a2 * b1 [m5]
+-------+-------+
a1 * b1 [m6]
+-------+-------+
_________________________________
product
+-------+-------+-------+
The least-significant words of intermediate multiplications [m1], [m2], and
[m4] are used only to develop a carry bit into the 48-bit sum. The product
is complemented if necessary to restore the sign.
Instead of implementing this algorithm directly, it is more efficient under
simulation to use 32 x 32 = 64-bit multiplications, thereby reducing the
number required from six to four. */
static void multiply (XPU *product, XPU multiplicand, XPU multiplier)
{
uint32 ah, al, bh, bl, carry, sign = 0;
t_uint64 hi, m1, m2, m3;
if ((multiplicand.mantissa == 0) || (multiplier.mantissa == 0)) /* x * 0 = 0 */
product->mantissa = product->exponent = 0;
else {
if (multiplicand.mantissa < 0) { /* negative? */
complement (&multiplicand); /* complement operand */
sign = ~sign; } /* track sign */
if (multiplier.mantissa < 0) { /* negative? */
complement (&multiplier); /* complement operand */
sign = ~sign; } /* track sign */
product->exponent = multiplicand.exponent + /* compute exponent */
multiplier.exponent + 1;
ah = (uint32) (multiplicand.mantissa >> 32); /* split multiplicand */
al = (uint32) multiplicand.mantissa; /* into high and low parts */
bh = (uint32) (multiplier.mantissa >> 32); /* split multiplier */
bl = (uint32) multiplier.mantissa; /* into high and low parts */
hi = ((t_uint64) ah * bh); /* form four cross products */
m1 = ((t_uint64) ah * bl); /* using 32 x 32 = 64-bit */
m2 = ((t_uint64) al * bh); /* hardware multiplies */
m3 = ((t_uint64) al * bl);
carry = ((uint32) m1 + (uint32) m2 + /* form a carry bit */
(uint32) (m3 >> 32)) >> (31 - XP_V_UMANT); /* and align to LSB - 1 */
product->mantissa = (hi + (m1 >> 32) + /* align, sum, and mask */
(m2 >> 32) + carry) & XP_USMANT;
if (sign) complement (product); } /* negate if required */
return;
}
/* Divide two unpacked numbers
The firmware performs division by calculating (1.0 / divisor) and then
multiplying by the dividend. The simulator uses 64-bit division and uses a
"divide-and-correct" algorithm similar to the one employed by the base set
single-precision floating-point division routine. */
static void divide (XPU *quotient, XPU dividend, XPU divisor)
{
t_int64 bh, bl, m1, m2, m3, m4;
if (divisor.mantissa == 0) { /* division by zero? */
if (dividend.mantissa < 0)
quotient->mantissa = XP_MSIGN; /* return minus infinity */
else quotient->mantissa = XP_MANT; /* or plus infinity */
quotient->exponent = XP_MAXEXP + 1; }
else if (dividend.mantissa == 0) /* dividend zero? */
quotient->mantissa = quotient->exponent = 0; /* yes; result is zero */
else {
quotient->exponent = dividend.exponent - /* division subtracts exponents */
divisor.exponent + 1;
bh = divisor.mantissa >> 32; /* split divisor */
bl = divisor.mantissa & 0xFFFFFFFF;
m1 = (dividend.mantissa >> 2) / bh; /* form 1st partial quotient */
m2 = (dividend.mantissa >> 2) % bh; /* obtain remainder */
m3 = bl * m1; /* calculate correction */
m4 = ((m2 - (m3 >> 32)) << 32) / bh; /* form 2nd partial quotient */
quotient->mantissa = (m1 << 32) + m4; /* merge quotients */
}
return;
}
#endif
/* Global routines */
/* Extended-precision memory read */
XPN ReadX (uint32 va)
{
XPN packed;
packed.high = ReadW (va) << 16 | ReadW ((va + 1) & VAMASK);
packed.low = ReadW ((va + 2) & VAMASK) << 16; /* read and pack */
return packed;
}
/* Extended-precision memory write */
void WriteX (uint32 va, XPN packed)
{
WriteW (va, (packed.high >> 16) & DMASK); /* write high word */
WriteW ((va + 1) & VAMASK, packed.high & DMASK); /* write middle word */
WriteW ((va + 2) & VAMASK, (packed.low >> 16) & DMASK); /* write low word */
}
#if defined (HAVE_INT64)
/* Extended-precision add */
uint32 x_add (XPN *sum, XPN augend, XPN addend)
{
XPU usum, uaddend, uaugend;
uaugend = unpack (augend); /* unpack augend */
uaddend = unpack (addend); /* unpack addend */
add (&usum, uaugend, uaddend); /* calculate sum */
return pack (sum, usum); /* pack sum */
}
/* Extended-precision subtract */
uint32 x_sub (XPN *difference, XPN minuend, XPN subtrahend)
{
XPU udifference, uminuend, usubtrahend;
uminuend = unpack (minuend); /* unpack minuend */
usubtrahend = unpack (subtrahend); /* unpack subtrahend */
complement (&usubtrahend); /* calculate difference */
add (&udifference, uminuend, usubtrahend); /* pack difference */
return pack (difference, udifference);
}
/* Extended-precision multiply */
uint32 x_mpy (XPN *product, XPN multiplicand, XPN multiplier)
{
XPU uproduct, umultiplicand, umultiplier;
umultiplicand = unpack (multiplicand); /* unpack multiplicand */
umultiplier = unpack (multiplier); /* unpack multiplier */
multiply (&uproduct, umultiplicand, umultiplier); /* calculate product */
return pack (product, uproduct); /* pack product */
}
/* Extended-precision divide */
uint32 x_div (XPN *quotient, XPN dividend, XPN divisor)
{
XPU uquotient, udividend, udivisor;
udividend = unpack (dividend); /* unpack dividend */
udivisor = unpack (divisor); /* unpack divisor */
divide (&uquotient, udividend, udivisor); /* calculate quotient */
return pack (quotient, uquotient); /* pack quotient */
}
/* Pack an extended-precision number
An unpacked mantissa is passed as a "packed" number with an unused exponent.
*/
uint32 x_pak (XPN *result, XPN mantissa, int32 exponent)
{
XPU unpacked;
unpacked.mantissa = TO_INT64 (mantissa); /* retrieve mantissa */
unpacked.exponent = exponent; /* and exponent */
return pack (result, unpacked); /* pack them */
}
/* Complement an extended-precision mantissa
An unpacked mantissa is passed as a "packed" number with an unused exponent.
We return the exponent increment, i.e., either zero or one, depending on
whether a renormalization was required. */
uint32 x_com (XPN *mantissa)
{
XPU unpacked;
unpacked.mantissa = TO_INT64 (*mantissa); /* retrieve mantissa */
unpacked.exponent = 0; /* exponent is irrelevant */
complement (&unpacked); /* negate it */
*mantissa = to_xpn (unpacked.mantissa, 0); /* replace mantissa */
return (uint32) unpacked.exponent; /* return exponent increment */
}
/* Complement an extended-precision number */
uint32 x_dcm (XPN *packed)
{
XPU unpacked;
unpacked = unpack (*packed); /* unpack the number */
complement (&unpacked); /* negate it */
return pack (packed, unpacked); /* and repack */
}
/* Truncate an extended-precision number */
void x_trun (XPN *result, XPN source)
{
t_uint64 mask;
uint32 bitslost;
XPU unpacked;
const XPU one = { XP_ONEHALF, 1 }; /* 0.5 * 2 ** 1 = 1.0 */
unpacked = unpack (source);
if (unpacked.exponent < 0) /* number < 0.5? */
result->high = result->low = 0; /* return 0 */
else if (unpacked.exponent > XP_W_MANT) /* no fractional bits? */
*result = source; /* already integer */
else {
mask = (XP_MANT >> unpacked.exponent) & XP_MANT;/* mask fractional bits */
bitslost = (uint32) (unpacked.mantissa & mask); /* flag if bits lost */
unpacked.mantissa = unpacked.mantissa & ~mask; /* mask off fraction */
if ((unpacked.mantissa < 0) && bitslost) /* negative? */
add (&unpacked, unpacked, one); /* truncate toward zero */
pack (result, unpacked); } /* (overflow cannot occur) */
return;
}
#endif /* defined (HAVE_INT64) */

52
HP2100/hp2100_fp1.h Normal file
View file

@ -0,0 +1,52 @@
/* hp2100_fp1.h: HP 2100/21MX extended-precision floating point definitions
Copyright (c) 2005, J. David Bryan
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 the author shall not
be used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from the author.
*/
#ifndef _HP2100_FP1_H_
#define _HP2100_FP1_H_ 0
/* HP memory representation of an extended-precision number */
typedef struct { uint32 high;
uint32 low; } XPN;
#define AS_XPN(x) (*(XPN *) &(x)) /* view as XPN */
XPN ReadX (uint32 va);
void WriteX (uint32 va, XPN packed);
uint32 x_add (XPN *sum, XPN augend, XPN addend);
uint32 x_sub (XPN *difference, XPN minuend, XPN subtrahend);
uint32 x_mpy (XPN *product, XPN multiplicand, XPN multiplier);
uint32 x_div (XPN *quotient, XPN dividend, XPN divisor);
uint32 x_pak (XPN *result, XPN mantissa, int32 exponent);
uint32 x_com (XPN *mantissa);
uint32 x_dcm (XPN *packed);
void x_trun (XPN *result, XPN source);
#endif

View file

@ -26,6 +26,7 @@
ms 13181A 7970B 800bpi nine track magnetic tape
13183A 7970E 1600bpi nine track magnetic tape
01-Mar-05 JDB Added SET OFFLINE; rewind/offline now does not detach
07-Oct-04 JDB Fixed enable/disable from either device
14-Aug-04 JDB Fixed many functional and timing problems (from Dave Bryan)
- fixed erroneous execution of rejected command
@ -75,6 +76,9 @@
#include "hp2100_defs.h"
#include "sim_tape.h"
#define UNIT_V_OFFLINE (MTUF_V_UF + 0) /* unit offline */
#define UNIT_OFFLINE (1 << UNIT_V_OFFLINE)
#define MS_NUMDR 4 /* number of drives */
#define DB_N_SIZE 16 /* max data buf */
#define DBSIZE (1 << DB_N_SIZE) /* max data cmd */
@ -190,6 +194,7 @@ t_stat msc_svc (UNIT *uptr);
t_stat msc_reset (DEVICE *dptr);
t_stat msc_attach (UNIT *uptr, char *cptr);
t_stat msc_detach (UNIT *uptr);
t_stat msc_online (UNIT *uptr, int32 value, char *cptr, void *desc);
t_stat msc_boot (int32 unitno, DEVICE *dptr);
t_stat ms_map_err (UNIT *uptr, t_stat st);
t_stat ms_settype (UNIT *uptr, int32 val, char *cptr, void *desc);
@ -250,10 +255,14 @@ DEVICE msd_dev = {
*/
UNIT msc_unit[] = {
{ UDATA (&msc_svc, UNIT_ATTABLE + UNIT_ROABLE + UNIT_DISABLE, 0) },
{ UDATA (&msc_svc, UNIT_ATTABLE + UNIT_ROABLE + UNIT_DISABLE, 0) },
{ UDATA (&msc_svc, UNIT_ATTABLE + UNIT_ROABLE + UNIT_DISABLE, 0) },
{ UDATA (&msc_svc, UNIT_ATTABLE + UNIT_ROABLE + UNIT_DISABLE, 0) } };
{ UDATA (&msc_svc, UNIT_ATTABLE | UNIT_ROABLE |
UNIT_DISABLE | UNIT_OFFLINE, 0) },
{ UDATA (&msc_svc, UNIT_ATTABLE | UNIT_ROABLE |
UNIT_DISABLE | UNIT_OFFLINE, 0) },
{ UDATA (&msc_svc, UNIT_ATTABLE | UNIT_ROABLE |
UNIT_DISABLE | UNIT_OFFLINE, 0) },
{ UDATA (&msc_svc, UNIT_ATTABLE | UNIT_ROABLE |
UNIT_DISABLE | UNIT_OFFLINE, 0) } };
REG msc_reg[] = {
{ ORDATA (STA, msc_sta, 12) },
@ -282,6 +291,8 @@ REG msc_reg[] = {
{ NULL } };
MTAB msc_mod[] = {
{ UNIT_OFFLINE, UNIT_OFFLINE, "offline", "OFFLINE", NULL },
{ UNIT_OFFLINE, 0, "online", "ONLINE", msc_online },
{ MTUF_WLK, 0, "write enabled", "WRITEENABLED", NULL },
{ MTUF_WLK, MTUF_WLK, "write locked", "LOCKED", NULL },
{ MTAB_XTD|MTAB_VUN, 0, "REEL", "REEL",
@ -396,7 +407,7 @@ case ioLIX: /* load */
dat = 0;
case ioMIX: /* merge */
dat = dat | (msc_sta & ~STA_DYN); /* get card status */
if (uptr->flags & UNIT_ATT) { /* online? */
if ((uptr->flags & UNIT_OFFLINE) == 0) { /* online? */
dat = dat | uptr->UST; /* add unit status */
if (sim_is_active (uptr) && /* TBSY unless RWD at BOT */
!((uptr->FNC & FNF_RWD) && (uptr->UST & STA_BOT)))
@ -482,14 +493,17 @@ devc = msc_dib.devno; /* get device nos */
devd = msd_dib.devno;
unum = uptr - msc_dev.units; /* get unit number */
if ((uptr->FNC != FNC_RWS) && !(uptr->flags & UNIT_ATT)) { /* offline? */
if ((uptr->FNC != FNC_RWS) && (uptr->flags & UNIT_OFFLINE)) { /* offline? */
msc_sta = (msc_sta | STA_REJ) & ~STA_BUSY; /* reject */
setFSR (devc); /* set cch flg */
return IORETURN (msc_stopioe, SCPE_UNATT); }
switch (uptr->FNC) { /* case on function */
case FNC_RWS: /* rewind offline */
detach_unit (uptr); /* detach == offline */
sim_tape_rewind (uptr); /* rewind tape */
uptr->flags = uptr->flags | UNIT_OFFLINE; /* set offline */
uptr->UST = STA_BOT; /* BOT when online again */
break; /* we're done */
case FNC_REW: /* rewind */
@ -680,7 +694,9 @@ t_stat msc_attach (UNIT *uptr, char *cptr)
t_stat r;
r = sim_tape_attach (uptr, cptr); /* attach unit */
if (r == SCPE_OK) uptr->UST = STA_BOT; /* tape starts at BOT */
if (r == SCPE_OK) {
uptr->flags = uptr->flags & ~UNIT_OFFLINE; /* set online */
uptr->UST = STA_BOT; } /* tape starts at BOT */
return r;
}
@ -689,9 +705,18 @@ return r;
t_stat msc_detach (UNIT* uptr)
{
uptr->UST = 0; /* update status */
uptr->flags = uptr->flags | UNIT_OFFLINE; /* set offline */
return sim_tape_detach (uptr); /* detach unit */
}
/* Online routine */
t_stat msc_online (UNIT *uptr, int32 value, char *cptr, void *desc)
{
if (uptr->flags & UNIT_ATT) return SCPE_OK;
else return SCPE_UNATT;
}
/* Configure timing */
void ms_config_timing (void)

View file

@ -1,6 +1,6 @@
/* id16_cpu.c: Interdata 16b CPU simulator
Copyright (c) 2000-2004, Robert M. Supnik
Copyright (c) 2000-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"),
@ -25,6 +25,8 @@
cpu Interdata 16b CPU
10-Mar-05 RMS Fixed bug in show history routine (from Mark Hittinger)
Revised examine/deposit to do words rather than bytes
07-Nov-04 RMS Added instruction history
22-Sep-03 RMS Added additional instruction decode types
07-Feb-03 RMS Fixed bug in SETM, SETMR (found by Mark Pizzolato)
@ -521,7 +523,7 @@ MTAB cpu_mod[] = {
DEVICE cpu_dev = {
"CPU", &cpu_unit, cpu_reg, cpu_mod,
1, 16, 18, 1, 16, 8,
1, 16, 18, 2, 16, 16,
&cpu_ex, &cpu_dep, &cpu_reset,
NULL, NULL, NULL,
&cpu_dib, 0 };
@ -1681,6 +1683,17 @@ M[loc >> 1] = ((loc & 1)?
((M[loc >> 1] & DMASK8) | (val << 8)));
return;
}
uint32 IOReadH (uint32 loc)
{
return (M[loc >> 1] & DMASK16);
}
void IOWriteH (uint32 loc, uint32 val)
{
M[loc >> 1] = val & DMASK16;
return;
}
/* Reset routine */
@ -1708,7 +1721,7 @@ if (sw & SWMASK ('V')) {
if (addr > VAMASK) return SCPE_NXM;
addr = (addr + ((addr & VA_S1)? s1_rel: s0_rel)) & PAMASK16E; }
if (addr >= MEMSIZE) return SCPE_NXM;
if (vptr != NULL) *vptr = IOReadB (addr);
if (vptr != NULL) *vptr = IOReadH (addr);
return SCPE_OK;
}
@ -1720,7 +1733,7 @@ if (sw & SWMASK ('V')) {
if (addr > VAMASK) return SCPE_NXM;
addr = (addr + ((addr & VA_S1)? s1_rel: s0_rel)) & PAMASK16E; }
if (addr >= MEMSIZE) return SCPE_NXM;
IOWriteB (addr, val & 0xFF);
IOWriteH (addr, val);
return SCPE_OK;
}
@ -1794,9 +1807,9 @@ return SCPE_OK;
t_stat cpu_show_hist (FILE *st, UNIT *uptr, int32 val, void *desc)
{
uint32 op, k, di, lnt;
int32 op, k, di, lnt;
char *cptr = (char *) desc;
t_value sim_eval[4];
t_value sim_eval[2];
t_stat r;
struct InstHistory *h;
extern t_stat fprint_sym (FILE *ofile, t_addr addr, t_value *val,
@ -1814,12 +1827,11 @@ for (k = 0; k < lnt; k++) { /* print specified */
h = &hst[(di++) % hst_lnt]; /* entry pointer */
if (h->vld) { /* instruction? */
fprintf (st, "%04X %04X %04X ", h->pc, h->r1, h->opnd);
sim_eval[0] = op = (h->ir1 >> 8) & 0xFF;
sim_eval[1] = h->ir1 & 0xFF;
sim_eval[2] = (h->ir2 >> 8) & 0xFF;
sim_eval[3] = h->ir2 & 0xFF;
op = (h->ir1 >> 8) & 0xFF;
if (OP_TYPE (op) >= OP_RX) fprintf (st, "%04X ", h->ea);
else fprintf (st, " ");
sim_eval[0] = h->ir1;
sim_eval[1] = h->ir2;
if ((fprint_sym (st, h->pc, sim_eval, &cpu_unit, SWMASK ('M'))) > 0)
fprintf (st, "(undefined) %04X", h->ir1);
fputc ('\n', st); /* end line */

View file

@ -45,8 +45,8 @@ extern UNIT cpu_unit;
extern REG cpu_reg[];
extern uint16 *M;
t_stat fprint_sym_m (FILE *of, t_addr addr, t_value *val, t_bool cf);
t_stat parse_sym_m (char *cptr, t_addr addr, t_value *val, t_bool cf);
t_stat fprint_sym_m (FILE *of, t_addr addr, t_value *val);
t_stat parse_sym_m (char *cptr, t_addr addr, t_value *val);
extern t_stat lp_load (FILE *fileref, char *cptr, char *fnam);
extern t_stat pt_dump (FILE *of, char *cptr, char *fnam);
@ -64,7 +64,7 @@ char sim_name[] = "Interdata 16b";
REG *sim_PC = &cpu_reg[0];
int32 sim_emax = 8;
int32 sim_emax = 2;
DEVICE *sim_devices[] = {
&cpu_dev,
@ -255,9 +255,6 @@ static const uint32 opc_val[] = {
0xEC00+I_RX, 0xED00+I_RX, 0xEE00+I_RX, 0xEF00+I_RX,
0xFFFF };
#define GETNUM(d,n) for (k = d = 0; k < n; k++) \
d = (d << 8) | (((uint32) val[vp++]) & 0xFF)
/* Symbolic decode
Inputs:
@ -274,38 +271,42 @@ static const uint32 opc_val[] = {
t_stat fprint_sym (FILE *of, t_addr addr, t_value *val,
UNIT *uptr, int32 sw)
{
int32 c, k, num, rdx, vp, lnt;
int32 c1, c2, rdx;
t_stat r;
DEVICE *dptr;
if (uptr == NULL) uptr = &cpu_unit; /* anon = CPU */
else if (uptr != &cpu_unit) return SCPE_ARG; /* CPU only */
dptr = find_dev_from_unit (uptr); /* find dev */
if (dptr == NULL) return SCPE_IERR;
if (dptr->dwidth != 8) return SCPE_ARG; /* byte dev only */
if (sw & SWMASK ('B')) lnt = 1; /* get length */
else if (sw & SWMASK ('W')) lnt = 2;
else if (sw & SWMASK ('F')) lnt = 4;
else lnt = (uptr == &cpu_unit)? 2: 1;
if (sw & SWMASK ('D')) rdx = 10; /* get radix */
else if (sw & SWMASK ('O')) rdx = 8;
else if (sw & SWMASK ('H')) rdx = 16;
else rdx = dptr->dradix;
vp = 0; /* init ptr */
if ((sw & SWMASK ('A')) || (sw & SWMASK ('C'))) { /* char format? */
if (sw & SWMASK ('C')) lnt = sim_emax; /* -c -> string */
if ((val[0] & 0x7F) == 0) return SCPE_ARG;
while (vp < lnt) { /* print string */
if ((c = (uint32) val[vp++] & 0x7F) == 0) break;
fprintf (of, (c < 0x20)? "<%02X>": "%c", c); }
return -(vp - 1); } /* return # chars */
if (sw & SWMASK ('A')) { /* ASCII char? */
c1 = (val[0] >> ((addr & 1)? 0: 8)) & 0x7F; /* get byte */
fprintf (of, (c1 < 0x20)? "<%02X>": "%c", c1);
return 0; }
if (sw & SWMASK ('B')) { /* byte? */
c1 = (val[0] >> ((addr & 1)? 0: 8)) & 0xFF; /* get byte */
fprint_val (of, c1, rdx, 8, PV_RZRO);
return 0; }
if (sw & SWMASK ('C')) { /* string? */
c1 = (val[0] >> 8) & 0x7F;
c2 = val[0] & 0x7F;
fprintf (of, (c1 < 0x20)? "<%02X>": "%c", c1);
fprintf (of, (c2 < 0x20)? "<%02X>": "%c", c2);
return -1; }
if (sw & SWMASK ('F')) { /* fullword? */
fprint_val (of, (val[0] << 16) | val[1], rdx, 32, PV_RZRO);
return -3; }
if (sw & SWMASK ('M')) { /* inst format? */
r = fprint_sym_m (of, addr, val, uptr == &cpu_unit); /* decode inst */
r = fprint_sym_m (of, addr, val); /* decode inst */
if (r <= 0) return r; }
GETNUM (num, lnt); /* get number */
fprint_val (of, num, rdx, lnt * 8, PV_RZRO);
return -(vp - 1);
fprint_val (of, val[0], rdx, 16, PV_RZRO);
return -1;
}
/* Symbolic decode for -m
@ -314,19 +315,18 @@ return -(vp - 1);
of = output stream
addr = current PC
*val = values to decode
cf = true if decoding for CPU
Outputs:
return = if >= 0, error code
if < 0, number of extra bytes retired
*/
t_stat fprint_sym_m (FILE *of, t_addr addr, t_value *val, t_bool cf)
t_stat fprint_sym_m (FILE *of, t_addr addr, t_value *val)
{
uint32 i, j, k, inst, r1, r2, ea, vp;
uint32 i, j, inst, r1, r2, ea, vp;
vp = 0;
GETNUM (inst, 2); /* first 16b */
GETNUM (ea, 2); /* second 16b */
inst = val[0]; /* first 16b */
ea = val[1]; /* second 16b */
for (i = 0; opcode[i] != NULL; i++) { /* loop thru ops */
j = (opc_val[i] >> I_V_FL) & I_M_FL; /* get class */
if ((opc_val[i] & 0xFFFF) == (inst & masks[j])) { /* match? */
@ -347,10 +347,8 @@ for (i = 0; opcode[i] != NULL; i++) { /* loop thru ops */
case I_V_SB: /* short branch */
fprintf (of, "%-X,", r1);
case I_V_SX: /* ext short branch */
if (cf) fprintf (of, "%-X", ((inst & MSK_SBF)?
fprintf (of, "%-X", ((inst & MSK_SBF)?
(addr + r2 + r2): (addr - r2 - r2)));
else fprintf (of, ((inst & MSK_SBF)?
".+%-X": ".-%X"), r2 + r2);
return -1;
case I_V_R: /* register */
fprintf (of, "R%d", r2);
@ -408,74 +406,74 @@ return reg;
*cptr = pointer to input string
**tptr = pointer to moved pointer
*ea = effective address
*rel = relative flag
addr = base address
cf = true if parsing for CPU
Outputs:
status = SCPE_OK if ok, else error code
*/
t_stat get_addr (char *cptr, char **tptr, t_addr *ea, t_bool *rel,
t_addr addr, t_bool cf)
t_stat get_addr (char *cptr, char **tptr, t_addr *ea, t_addr addr)
{
int32 sign = 1;
*ea = 0;
if (*cptr == '.') { /* relative? */
*rel = TRUE;
cptr++;
if (cf) *ea = addr;
*ea = addr;
if (*cptr == '+') cptr++; /* .+? */
else if (*cptr == '-') { /* .-? */
sign = -1;
cptr++; }
else return SCPE_OK; }
else *rel = FALSE;
else *ea = 0;
errno = 0;
*ea = *ea + (sign * ((int32) strtoul (cptr, tptr, 16)));
if (errno || (cptr == *tptr)) return SCPE_ARG;
return SCPE_OK;
}
#define PUTNUM(d,n) for (k = n; k > 0; k--) \
val[vp++] = (d >> ((k - 1) * 8)) & 0xFF
/* Symbolic input */
t_stat parse_sym (char *cptr, t_addr addr, UNIT *uptr, t_value *val, int32 sw)
{
int32 k, rdx, lnt, num, vp;
int32 by, rdx, num;
t_stat r;
DEVICE *dptr;
static const uint32 maxv[5] = { 0, 0xFF, 0xFFFF, 0, 0xFFFFFFFF };
if (uptr == NULL) uptr = &cpu_unit; /* anon = CPU */
else if (uptr != &cpu_unit) return SCPE_ARG; /* CPU only */
dptr = find_dev_from_unit (uptr); /* find dev */
if (dptr == NULL) return SCPE_IERR;
if (dptr->dwidth != 8) return SCPE_ARG; /* byte dev only */
if (sw & SWMASK ('B')) lnt = 1; /* get length */
else if (sw & SWMASK ('W')) lnt = 2;
else if (sw & SWMASK ('F')) lnt = 4;
else lnt = (uptr == &cpu_unit)? 2: 1;
if (sw & SWMASK ('D')) rdx = 10; /* get radix */
else if (sw & SWMASK ('O')) rdx = 8;
else if (sw & SWMASK ('H')) rdx = 16;
else rdx = dptr->dradix;
vp = 0;
if ((sw & SWMASK ('A')) || (sw & SWMASK ('C'))) { /* char format? */
if (sw & SWMASK ('C')) lnt = sim_emax; /* -c -> string */
if (*cptr == 0) return SCPE_ARG;
while ((vp < lnt) && *cptr) { /* get chars */
val[vp++] = *cptr++; }
return -(vp - 1); } /* return # chars */
r = parse_sym_m (cptr, addr, val, uptr == &cpu_unit); /* try to parse inst */
if ((sw & SWMASK ('A')) || ((*cptr == '\'') && cptr++)) { /* ASCII char? */
if (cptr[0] == 0) return SCPE_ARG; /* must have 1 char */
if (addr & 1) val[0] = (val[0] & ~0xFF) | ((t_value) cptr[0]);
else val[0] = (val[0] & 0xFF) | (((t_value) cptr[0]) << 8);
return 0; }
if (sw & SWMASK ('B')) { /* byte? */
by = get_uint (cptr, rdx, DMASK8, &r); /* get byte */
if (r != SCPE_OK) return SCPE_ARG;
if (addr & 1) val[0] = (val[0] & ~0xFF) | by;
else val[0] = (val[0] & 0xFF) | (by << 8);
return 0; }
if ((sw & SWMASK ('C')) || ((*cptr == '"') && cptr++)) { /* ASCII chars? */
if (cptr[0] == 0) return SCPE_ARG; /* must have 1 char */
val[0] = ((t_value) cptr[0] << 8) | (t_value) cptr[1];
return -1; }
if (sw & SWMASK ('F')) {
num = (int32) get_uint (cptr, rdx, DMASK32, &r);/* get number */
if (r != SCPE_OK) return r;
val[0] = (num >> 16) & DMASK16;
val[1] = num & DMASK16;
return -3; }
r = parse_sym_m (cptr, addr, val); /* try to parse inst */
if (r <= 0) return r;
num = (int32) get_uint (cptr, rdx, maxv[lnt], &r); /* get number */
val[0] = (int32) get_uint (cptr, rdx, DMASK16, &r); /* get number */
if (r != SCPE_OK) return r;
PUTNUM (num, lnt); /* store */
return -(lnt - 1);
return -1;
}
/* Symbolic input for -m
@ -490,15 +488,13 @@ return -(lnt - 1);
<= 0 -number of extra words
*/
t_stat parse_sym_m (char *cptr, t_addr addr, t_value *val, t_bool cf)
t_stat parse_sym_m (char *cptr, t_addr addr, t_value *val)
{
uint32 i, j, k, t, df, db, inst, vp;
uint32 i, j, t, df, db, inst;
int32 st, r1, r2;
t_bool rel;
t_stat r;
char *tptr, gbuf[CBUFSIZE];
vp = 0;
cptr = get_glyph (cptr, gbuf, 0); /* get opcode */
for (i = 0; (opcode[i] != NULL) && (strcmp (opcode[i], gbuf) != 0) ; i++) ;
if (opcode[i] == NULL) return SCPE_ARG;
@ -527,45 +523,35 @@ case I_V_R: /* register */
case I_V_FX: /* float-memory */
case I_V_MX: case I_V_RX: /* mask/reg-mem */
case I_V_X: /* memory */
r = get_addr (gbuf, &tptr, &t, &rel, addr, cf); /* get addr */
if ((r != SCPE_OK) || (t > PAMASK16) ||
(!cf && rel)) return SCPE_ARG;
r = get_addr (gbuf, &tptr, &t, addr); /* get addr */
if ((r != SCPE_OK) || (t > PAMASK16)) return SCPE_ARG;
if (*tptr == '(') { /* index? */
if ((r2 = get_reg (tptr + 1, &tptr, R_R)) < 0)
return SCPE_ARG;
if (*tptr++ != ')') return SCPE_ARG;
inst = inst | r2; } /* or in R2 */
if (*tptr != 0) return SCPE_ARG;
PUTNUM (inst, 2);
PUTNUM (t, 2);
val[0] = inst;
val[1] = t;
return -3;
case I_V_SB: case I_V_SX: /* short branches */
r = get_addr (gbuf, &tptr, &t, &rel, addr, cf); /* get addr */
r = get_addr (gbuf, &tptr, &t, addr); /* get addr */
if ((r != SCPE_OK) || (t & 1) || *tptr) /* error if odd */
return SCPE_ARG;
st = t; /* signed version */
if (cf) { /* for CPU? */
db = (addr - t) & 0x1F; /* back displ */
df = (t - addr) & 0x1F; /* fwd displ */
if ((t == ((addr - db) & VAMASK16)) && /* back work and */
((j == I_V_SX) || !(inst & MSK_SBF))) /* ext or back br? */
inst = inst | (db >> 1); /* or in back displ */
else if ((t == ((addr + df) & VAMASK16)) && /* fwd work and */
((j == I_V_SX) || (inst & MSK_SBF))) /* ext or fwd br? */
inst = inst | (df >> 1) | MSK_SBF; /* or in fwd displ */
else return SCPE_ARG; }
else if (rel) { /* periph, must be rel */
if ((st <= 0) && (st >= -0x1F) && /* relative back? */
((j == I_V_SX) || !(inst & MSK_SBF)))
inst = inst | ((-st & 0x1F) >> 1);
else if ((st >= 0) && (st < 0x1F) && /* relative fwd? */
((j == I_V_SX) || (inst & MSK_SBF)))
inst = inst | ((t & 0x1F) >> 1);
else return SCPE_ARG; }
else return SCPE_ARG; /* periph & ~rel, err */
db = (addr - t) & 0x1F; /* back displ */
df = (t - addr) & 0x1F; /* fwd displ */
if ((t == ((addr - db) & VAMASK16)) && /* back work and */
((j == I_V_SX) || !(inst & MSK_SBF))) /* ext or back br? */
inst = inst | (db >> 1); /* or in back displ */
else if ((t == ((addr + df) & VAMASK16)) && /* fwd work and */
((j == I_V_SX) || (inst & MSK_SBF))) /* ext or fwd br? */
inst = inst | (df >> 1) | MSK_SBF; /* or in fwd displ */
else return SCPE_ARG;
break;
} /* end case */
PUTNUM (inst, 2);
val[0] = inst;
return -1;
}

View file

@ -25,6 +25,9 @@
cpu Interdata 32b CPU
10-Mar-05 RMS Fixed bug in initial memory allocation
RMS Fixed bug in show history routine (from Mark Hittinger)
RMS Revised examine/deposit to do words rather than bytes
18-Feb-05 RMS Fixed branches to mask new PC (from Greg Johnson)
06-Nov-04 RMS Added =n to SHOW HISTORY
25-Jan-04 RMS Revised for device debug support
@ -574,7 +577,7 @@ DEBTAB cpu_deb[] = {
DEVICE cpu_dev = {
"CPU", &cpu_unit, cpu_reg, cpu_mod,
1, 16, 20, 1, 16, 8,
1, 16, 20, 2, 16, 16,
&cpu_ex, &cpu_dep, &cpu_reset,
NULL, NULL, NULL,
&cpu_dib, DEV_DEBUG, 0,
@ -1870,6 +1873,8 @@ return 0; /* ok */
WriteF write fullword (processor)
IOReadB read byte (IO)
IOWriteB write byte (IO)
IOReadH read halfword (IO)
IOWriteH write halfword (IO)
*/
uint32 ReadB (uint32 loc, uint32 rel)
@ -1987,6 +1992,11 @@ uint32 sc = (3 - (loc & 3)) << 3;
return (M[loc >> 2] >> sc) & DMASK8;
}
uint32 IOReadH (uint32 loc)
{
return (M[loc >> 2] >> ((loc & 2)? 0: 16)) & DMASK16;
}
void IOWriteB (uint32 loc, uint32 val)
{
uint32 sc = (3 - (loc & 3)) << 3;
@ -1995,6 +2005,15 @@ val = val & DMASK8;
M[loc >> 2] = (M[loc >> 2] & ~(DMASK8 << sc)) | (val << sc);
return;
}
void IOWriteH (uint32 loc, uint32 val)
{
uint32 sc = (loc & 2)? 0: 16;
val = val & DMASK16;
M[loc >> 2] = (M[loc >> 2] & ~(DMASK16 << sc)) | (val << sc);
return;
}
/* Reset routine */
@ -2008,7 +2027,7 @@ DR = 0; /* clear display */
drmod = 0;
blk_io.dfl = blk_io.cur = blk_io.end = 0; /* no block I/O */
sim_brk_types = sim_brk_dflt = SWMASK ('E'); /* init bkpts */
if (M == NULL) M = calloc (MAXMEMSIZE32 >> 1, sizeof (uint16));
if (M == NULL) M = calloc (MAXMEMSIZE32 >> 2, sizeof (uint32));
if (M == NULL) return SCPE_MEM;
pcq_r = find_reg ("PCQ", NULL, dptr); /* init PCQ */
if (pcq_r) pcq_r->qptr = 0;
@ -2024,7 +2043,7 @@ if ((sw & SWMASK ('V')) && (PSW & PSW_REL)) {
int32 cc = RelocT (addr, MAC_BASE, P, &addr);
if (cc & (CC_C | CC_V)) return SCPE_NXM; }
if (addr >= MEMSIZE) return SCPE_NXM;
if (vptr != NULL) *vptr = IOReadB (addr);
if (vptr != NULL) *vptr = IOReadH (addr);
return SCPE_OK;
}
@ -2036,7 +2055,7 @@ if ((sw & SWMASK ('V')) && (PSW & PSW_REL)) {
int32 cc = RelocT (addr, MAC_BASE, P, &addr);
if (cc & (CC_C | CC_V)) return SCPE_NXM; }
if (addr >= MEMSIZE) return SCPE_NXM;
IOWriteB (addr, val & 0xFF);
IOWriteH (addr, val);
return SCPE_OK;
}
@ -2108,9 +2127,9 @@ return SCPE_OK;
t_stat cpu_show_hist (FILE *st, UNIT *uptr, int32 val, void *desc)
{
uint32 op, k, di, lnt;
int32 op, k, di, lnt;
char *cptr = (char *) desc;
t_value sim_eval[6];
t_value sim_eval[3];
t_stat r;
struct InstHistory *h;
extern t_stat fprint_sym (FILE *ofile, t_addr addr, t_value *val,
@ -2128,14 +2147,12 @@ for (k = 0; k < lnt; k++) { /* print specified */
h = &hst[(di++) % hst_lnt]; /* entry pointer */
if (h->pc & HIST_PC) { /* instruction? */
fprintf (st, "%06X %08X %08X ", h->pc & VAMASK32, h->r1, h->opnd);
sim_eval[0] = op = (h->ir1 >> 8) & 0xFF;
sim_eval[1] = h->ir1 & 0xFF;
sim_eval[2] = (h->ir2 >> 8) & 0xFF;
sim_eval[3] = h->ir2 & 0xFF;
sim_eval[4] = (h->ir3 >> 8) & 0xFF;
sim_eval[5] = h->ir3 & 0xFF;
op = (h->ir1 >> 8) & 0xFF;
if (OP_TYPE (op) >= OP_RX) fprintf (st, "%06X ", h->ea);
else fprintf (st, " ");
sim_eval[0] = h->ir1;
sim_eval[1] = h->ir2;
sim_eval[2] = h->ir3;
if ((fprint_sym (st, h->pc & VAMASK32, sim_eval, &cpu_unit, SWMASK ('M'))) > 0)
fprintf (st, "(undefined) %04X", h->ir1);
fputc ('\n', st); /* end line */

View file

@ -48,8 +48,8 @@ extern UNIT cpu_unit;
extern REG cpu_reg[];
extern uint32 *M;
t_stat fprint_sym_m (FILE *of, t_addr addr, t_value *val, t_bool cf);
t_stat parse_sym_m (char *cptr, t_addr addr, t_value *val, t_bool cf);
t_stat fprint_sym_m (FILE *of, t_addr addr, t_value *val);
t_stat parse_sym_m (char *cptr, t_addr addr, t_value *val);
extern t_stat lp_load (FILE *fileref, char *cptr, char *fnam);
extern t_stat pt_dump (FILE *of, char *cptr, char *fnam);
@ -290,7 +290,7 @@ static const uint32 opc_val[] = {
/* Print an RX specifier */
t_stat fprint_addr (FILE *of, t_addr addr, uint32 rx, uint32 ea1,
uint32 ea2, t_bool cf)
uint32 ea2)
{
uint32 rx2;
@ -299,25 +299,17 @@ if ((ea1 & 0xC000) == 0) { /* RX1 */
if (rx) fprintf (of, "(R%d)", rx);
return -3; }
if (ea1 & 0x8000) { /* RX2 */
if (cf) { /* for CPU? */
ea1 = addr + 4 + SEXT15 (ea1);
fprintf (of, "%-X", ea1 & VAMASK32); }
else { /* for dev */
int32 disp = SEXT15 (ea1); /* get disp */
if (disp >= -4) fprintf (of, ".+%-X", disp + 4);
else fprintf (of, ".-%-X", -4 - disp); }
ea1 = addr + 4 + SEXT15 (ea1);
fprintf (of, "%-X", ea1 & VAMASK32);
if (rx) fprintf (of, "(R%d)", rx);
return -3; }
rx2 = (ea1 >> 8) & 0xF;
rx2 = (ea1 >> 8) & 0xF; /* RX3 */
fprintf (of, "%-X", ((ea1 << 16) | ea2) & VAMASK32);
if (rx && !rx2) fprintf (of, "(R%d)", rx);
if (rx2) fprintf (of, "(R%d,R%d)", rx, rx2);
return -5;
}
#define GETNUM(d,n) for (k = d = 0; k < n; k++) \
d = (d << 8) | (((uint32) val[vp++]) & 0xFF)
/* Symbolic decode
Inputs:
@ -334,39 +326,42 @@ return -5;
t_stat fprint_sym (FILE *of, t_addr addr, t_value *val,
UNIT *uptr, int32 sw)
{
int32 c, k, num, rdx, vp, lnt;
int32 c1, c2, rdx;
t_stat r;
DEVICE *dptr;
if (uptr == NULL) uptr = &cpu_unit; /* anon = CPU */
else if (uptr != &cpu_unit) return SCPE_ARG; /* only for CPU */
dptr = find_dev_from_unit (uptr); /* find dev */
if (dptr == NULL) return SCPE_IERR;
if (dptr->dwidth != 8) return SCPE_ARG; /* byte dev only */
if (sw & SWMASK ('B')) lnt = 1; /* get length */
else if (sw & SWMASK ('W')) lnt = 2;
else if (sw & SWMASK ('F')) lnt = 4;
else lnt = (uptr == &cpu_unit)? 4: 1;
if (sw & SWMASK ('D')) rdx = 10; /* get radix */
else if (sw & SWMASK ('O')) rdx = 8;
else if (sw & SWMASK ('H')) rdx = 16;
else rdx = dptr->dradix;
vp = 0; /* init ptr */
if ((sw & SWMASK ('A')) || (sw & SWMASK ('C'))) { /* char format? */
if (sw & SWMASK ('C')) lnt = sim_emax; /* -c -> string */
if ((val[0] & 0x7F) == 0) return SCPE_ARG;
while (vp < lnt) { /* print string */
if ((c = (uint32) val[vp++] & 0x7F) == 0) break;
fprintf (of, (c < 0x20)? "<%02X>": "%c", c); }
return -(vp - 1); } /* return # chars */
if (sw & SWMASK ('A')) { /* ASCII char? */
c1 = (val[0] >> ((addr & 1)? 0: 8)) & 0x7F; /* get byte */
fprintf (of, (c1 < 0x20)? "<%02X>": "%c", c1);
return 0; }
if (sw & SWMASK ('B')) { /* byte? */
c1 = (val[0] >> ((addr & 1)? 0: 8)) & 0xFF; /* get byte */
fprint_val (of, c1, rdx, 8, PV_RZRO);
return 0; }
if (sw & SWMASK ('C')) { /* string? */
c1 = (val[0] >> 8) & 0x7F;
c2 = val[0] & 0x7F;
fprintf (of, (c1 < 0x20)? "<%02X>": "%c", c1);
fprintf (of, (c2 < 0x20)? "<%02X>": "%c", c2);
return -1; }
if (sw & SWMASK ('H')) { /* halfword? */
fprint_val (of, val[0], rdx, 16, PV_RZRO);
return -1; }
if (sw & SWMASK ('M')) { /* inst format? */
r = fprint_sym_m (of, addr, val, uptr == &cpu_unit); /* decode inst */
if (r <= 0) return r; /* success? */
lnt = 2; } /* no, skip 16b */
r = fprint_sym_m (of, addr, val); /* decode inst */
if (r <= 0) return r; }
GETNUM (num, lnt); /* get number */
fprint_val (of, num, rdx, lnt * 8, PV_RZRO);
return -(vp - 1);
fprint_val (of, (val[0] << 16) | val[1], rdx, 32, PV_RZRO);
return -3;
}
/* Symbolic decode for -m
@ -381,14 +376,13 @@ return -(vp - 1);
if < 0, number of extra bytes retired
*/
t_stat fprint_sym_m (FILE *of, t_addr addr, t_value *val, t_bool cf)
t_stat fprint_sym_m (FILE *of, t_addr addr, t_value *val)
{
uint32 i, j, k, inst, r1, r2, ea1, ea2, vp;
uint32 i, j, inst, r1, r2, ea1, ea2;
vp = 0;
GETNUM (inst,2); /* high 16b */
GETNUM (ea1, 2); /* next 16b */
GETNUM (ea2, 2); /* next 16b */
inst = val[0];
ea1 = val[1];
ea2 = val[2];
for (i = 0; opc_val[i] != 0xFFFF; i++) { /* loop thru ops */
j = (opc_val[i] >> I_V_FL) & I_M_FL; /* get class */
if ((opc_val[i] & 0xFFFF) == (inst & masks[j])) { /* match? */
@ -409,10 +403,8 @@ for (i = 0; opc_val[i] != 0xFFFF; i++) { /* loop thru ops */
case I_V_SB: /* short branch */
fprintf (of, "%-X,", r1);
case I_V_SX: /* ext short branch */
if (cf) fprintf (of, "%-X", ((inst & MSK_SBF)?
fprintf (of, "%-X", ((inst & MSK_SBF)?
(addr + r2 + r2): (addr - r2 - r2)));
else fprintf (of, ((inst & MSK_SBF)?
".+%-X": ".-%X"), r2 + r2);
return -1;
case I_V_R: /* register */
fprintf (of, "R%d", r2);
@ -427,14 +419,16 @@ for (i = 0; opc_val[i] != 0xFFFF; i++) { /* loop thru ops */
return -5;
case I_V_MX: /* mask-memory */
fprintf (of, "%-X,", r1);
return fprint_addr (of, addr, r2, ea1, ea2, cf);
return fprint_addr (of, addr, r2, ea1, ea2);
case I_V_RX: /* register-memory */
case I_V_FX: /* floating-memory */
fprintf (of, "R%d,", r1);
case I_V_X: /* memory */
return fprint_addr (of, addr, r2, ea1, ea2, cf); }
return SCPE_IERR; } /* end if */
} /* end for */
return fprint_addr (of, addr, r2, ea1, ea2);
} /* end case */
return SCPE_IERR;
} /* end if */
} /* end for */
return SCPE_ARG; /* no match */
}
@ -503,74 +497,74 @@ return SCPE_OK;
*cptr = pointer to input string
**tptr = pointer to moved pointer
*ea = effective address
*rel = relative flag
addr = base address
cf = true if parsing for CPU
Outputs:
status = SCPE_OK if ok, else error code
*/
t_stat get_addr (char *cptr, char **tptr, t_addr *ea, t_bool *rel,
t_addr addr, t_bool cf)
t_stat get_addr (char *cptr, char **tptr, t_addr *ea, t_addr addr)
{
int32 sign = 1;
*ea = 0;
if (*cptr == '.') { /* relative? */
*rel = TRUE;
cptr++;
if (cf) *ea = addr;
*ea = addr;
if (*cptr == '+') cptr++; /* .+? */
else if (*cptr == '-') { /* .-? */
sign = -1;
cptr++; }
else return SCPE_OK; }
else *rel = FALSE;
else *ea = 0;
errno = 0;
*ea = *ea + (sign * ((int32) strtoul (cptr, tptr, 16)));
if (errno || (cptr == *tptr)) return SCPE_ARG;
return SCPE_OK;
}
#define PUTNUM(d,n) for (k = n; k > 0; k--) \
val[vp++] = (d >> ((k - 1) * 8)) & 0xFF
/* Symbolic input */
t_stat parse_sym (char *cptr, t_addr addr, UNIT *uptr, t_value *val, int32 sw)
{
int32 k, rdx, lnt, num, vp;
int32 by, rdx, num;
t_stat r;
DEVICE *dptr;
static const uint32 maxv[5] = { 0, 0xFF, 0xFFFF, 0, 0xFFFFFFFF };
if (uptr == NULL) uptr = &cpu_unit; /* anon = CPU */
else if (uptr != &cpu_unit) return SCPE_ARG; /* CPU only */
dptr = find_dev_from_unit (uptr); /* find dev */
if (dptr == NULL) return SCPE_IERR;
if (dptr->dwidth != 8) return SCPE_ARG; /* byte dev only */
if (sw & SWMASK ('B')) lnt = 1; /* get length */
else if (sw & SWMASK ('W')) lnt = 2;
else if (sw & SWMASK ('F')) lnt = 4;
else lnt = (uptr == &cpu_unit)? 4: 1;
if (sw & SWMASK ('D')) rdx = 10; /* get radix */
else if (sw & SWMASK ('O')) rdx = 8;
else if (sw & SWMASK ('H')) rdx = 16;
else rdx = dptr->dradix;
vp = 0;
if ((sw & SWMASK ('A')) || (sw & SWMASK ('C'))) { /* char format? */
if (sw & SWMASK ('C')) lnt = sim_emax; /* -c -> string */
if (*cptr == 0) return SCPE_ARG;
while ((vp < lnt) && *cptr) { /* get chars */
val[vp++] = *cptr++; }
return -(vp - 1); } /* return # chars */
r = parse_sym_m (cptr, addr, val, uptr == &cpu_unit); /* try to parse */
if ((sw & SWMASK ('A')) || ((*cptr == '\'') && cptr++)) { /* ASCII char? */
if (cptr[0] == 0) return SCPE_ARG; /* must have 1 char */
if (addr & 1) val[0] = (val[0] & ~0xFF) | ((t_value) cptr[0]);
else val[0] = (val[0] & 0xFF) | (((t_value) cptr[0]) << 8);
return 0; }
if (sw & SWMASK ('B')) { /* byte? */
by = get_uint (cptr, rdx, DMASK8, &r); /* get byte */
if (r != SCPE_OK) return SCPE_ARG;
if (addr & 1) val[0] = (val[0] & ~0xFF) | by;
else val[0] = (val[0] & 0xFF) | (by << 8);
return 0; }
if ((sw & SWMASK ('C')) || ((*cptr == '"') && cptr++)) { /* ASCII chars? */
if (cptr[0] == 0) return SCPE_ARG; /* must have 1 char */
val[0] = ((t_value) cptr[0] << 8) | (t_value) cptr[1];
return -1; }
if (sw & SWMASK ('H')) { /* halfword? */
val[0] = (int32) get_uint (cptr, rdx, DMASK16, &r); /* get number */
if (r != SCPE_OK) return r;
return -1; }
r = parse_sym_m (cptr, addr, val); /* try to parse inst */
if (r <= 0) return r;
num = (int32) get_uint (cptr, rdx, maxv[lnt], &r); /* get number */
num = (int32) get_uint (cptr, rdx, DMASK32, &r); /* get number */
if (r != SCPE_OK) return r;
PUTNUM (num, lnt); /* store */
return -(lnt - 1);
val[0] = (num >> 16) & DMASK16;
val[1] = num & DMASK16;
return -3;
}
/* Symbolic input for -m
@ -585,12 +579,11 @@ return -(lnt - 1);
<= 0 -number of extra words
*/
t_stat parse_sym_m (char *cptr, t_addr addr, t_value *val, t_bool cf)
t_stat parse_sym_m (char *cptr, t_addr addr, t_value *val)
{
uint32 i, j, k, df, db, t, inst, vp;
uint32 i, j, df, db, t, inst, vp;
int32 st, r1, r2, rx2;
t_stat r;
t_bool rel;
char *tptr, gbuf[CBUFSIZE];
vp = 0;
@ -622,7 +615,7 @@ case I_V_R: /* register */
case I_V_FX: /* float-memory */
case I_V_MX: case I_V_RX: /* mask/reg-memory */
case I_V_X: /* memory */
r = get_addr (gbuf, &tptr, &t, &rel, addr, cf); /* get addr */
r = get_addr (gbuf, &tptr, &t, addr); /* get addr */
if (r != SCPE_OK) return SCPE_ARG; /* error? */
rx2 = 0; /* assume no 2nd */
if (*tptr == '(') { /* index? */
@ -634,67 +627,52 @@ case I_V_X: /* memory */
return SCPE_ARG; }
if (*tptr++ != ')') return SCPE_ARG; } /* all done? */
if (*tptr != 0) return SCPE_ARG;
PUTNUM (inst, 2); /* store inst */
if (!cf && rel) { /* periph, rel */
st = t - 4; /* displ */
if (rx2 || (st > 0x3FFF) || (st < -0x4000)) /* rx2 or too big? */
return SCPE_ARG;
t = (st & 0x7FFF) | 0x8000;
PUTNUM (t, 2); /* store displ */
return -3; }
val[0] = inst; /* store inst */
if (rx2 == 0) { /* no 2nd? */
if (t < 0x4000) { /* RX1? */
PUTNUM (t, 2); /* store ea */
val[1] = t; /* store ea */
return -3; }
st = (t - (addr + 4)); /* displ */
if (cf && (st <= 0x3FFF) && (st >= -0x4000)) { /* RX2? CPU only */
if ((st <= 0x3FFF) && (st >= -0x4000)) { /* RX2? CPU only */
t = (st & 0x7FFF) | 0x8000;
PUTNUM (t, 2); /* store displ */
val[1] = t; /* store displ */
return -3; } }
t = (t & VAMASK32) | 0x40000000 | (rx2 << 24);
PUTNUM (t, 4); /* RX3 */
val[1] = (t >> 16) & DMASK16;
val[2] = t & DMASK16;
return -5;
case I_V_RI: /* 16b immediate */
r = get_imm (gbuf, &t, &inst, DMASK16); /* process imm */
if (r != SCPE_OK) return r;
PUTNUM (inst, 2); /* store inst */
PUTNUM (t, 2); /* store 16b imm */
val[0] = inst;
val[1] = t;
return -3;
case I_V_RF:
r = get_imm (gbuf, &t, &inst, DMASK32); /* process imm */
if (r != SCPE_OK) return r;
PUTNUM (inst, 2); /* store inst */
PUTNUM (t, 4); /* store 32b imm */
val[0] = inst;
val[1] = (t >> 16) & DMASK16;
val[2] = t & DMASK16;
return -5;
case I_V_SB: case I_V_SX: /* short branches */
r = get_addr (gbuf, &tptr, &t, &rel, addr, cf); /* get addr */
r = get_addr (gbuf, &tptr, &t, addr); /* get addr */
if ((r != SCPE_OK) || (t & 1) || *tptr) /* error if odd */
return SCPE_ARG;
st = t; /* signed version */
if (cf) { /* for CPU? */
db = (addr - t) & 0x1F; /* back displ */
df = (t - addr) & 0x1F; /* fwd displ */
if ((t == ((addr - db) & VAMASK16)) && /* back work and */
((j == I_V_SX) || !(inst & MSK_SBF))) /* ext or back br? */
inst = inst | (db >> 1); /* or in back displ */
else if ((t == ((addr + df) & VAMASK16)) && /* fwd work and */
((j == I_V_SX) || (inst & MSK_SBF))) /* ext or fwd br? */
inst = inst | (df >> 1) | MSK_SBF; /* or in fwd displ */
else return SCPE_ARG; }
else if (rel) { /* periph, must be rel */
if ((st <= 0) && (st >= -0x1F) && /* relative back? */
((j == I_V_SX) || !(inst & MSK_SBF)))
inst = inst | ((-st & 0x1F) >> 1);
else if ((st >= 0) && (st < 0x1F) && /* relative fwd? */
((j == I_V_SX) || (inst & MSK_SBF)))
inst = inst | ((t & 0x1F) >> 1);
else return SCPE_ARG; }
else return SCPE_ARG; /* periph & ~rel, err */
db = (addr - t) & 0x1F; /* back displ */
df = (t - addr) & 0x1F; /* fwd displ */
if ((t == ((addr - db) & VAMASK16)) && /* back work and */
((j == I_V_SX) || !(inst & MSK_SBF))) /* ext or back br? */
inst = inst | (db >> 1); /* or in back displ */
else if ((t == ((addr + df) & VAMASK16)) && /* fwd work and */
((j == I_V_SX) || (inst & MSK_SBF))) /* ext or fwd br? */
inst = inst | (df >> 1) | MSK_SBF; /* or in fwd displ */
else return SCPE_ARG;
} /* end case */
PUTNUM (inst, 2);
val[0] = inst;
return -1;
}

View file

@ -464,6 +464,8 @@ int32 int_chg (uint32 irq, int32 dat, int32 armdis);
int32 io_2b (int32 val, int32 pos, int32 old);
uint32 IOReadB (uint32 loc);
void IOWriteB (uint32 loc, uint32 val);
uint32 IOReadH (uint32 loc);
void IOWriteH (uint32 loc, uint32 val);
uint32 ReadF (uint32 loc, uint32 rel);
void WriteF (uint32 loc, uint32 val, uint32 rel);
uint32 IOReadBlk (uint32 loc, uint32 cnt, uint8 *buf);

View file

@ -1,14 +1,14 @@
To: Users
From: Bob Supnik
Subj: Interdata 16b/32b Simulator Usage
Date: 15-Nov-2004
Date: 15-Mar-2005
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
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"),
@ -166,17 +166,23 @@ 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 64KB.
These switches are recognized when examining or depositing in CPU memory
(or any other byte oriented device):
These switches are recognized when examining or depositing in CPU memory:
-a examine/deposit ASCII characters
-b examine/deposit bytes
-c examine/deposit packed ASCII characters
-w examine/deposit halfwords (CPU default)
-f examine/deposit fullwords
-d data radix is decimal
-o data radix is octal
-h data radix is hexadecimal
-m examine as instruction mnemonics
-v interpret address as virtual
Packed characters, halfwords, fullwords, and instructions must be aligned
on a halfword (16b) boundary. If an odd address is specified, the low
order bit is ignored.
CPU registers include the visible state of the processor as well as the
control registers for the interrupt system.
@ -234,17 +240,22 @@ 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 1024KB.
These switches are recognized when examining or depositing in CPU memory
(or any other byte oriented device):
These switches are recognized when examining or depositing in CPU memory:
-a examine/deposit ASCII characters
-b examine/deposit bytes
-w examine/deposit halfwords
-c examine/deposit packed ASCII characters
-f examine/deposit fullwords (CPU default)
-d data radix is decimal
-o data radix is octal
-h data radix is hexadecimal
-m examine as instruction mnemonics
-v interpret address as virtual
Packed characters, halfwords, fullwords, and instructions must be aligned
on a halfword (16b) boundary. If an odd address is specified, the low
order bit is ignored.
CPU registers include the visible state of the processor as well as the
control registers for the interrupt system.
@ -845,8 +856,8 @@ Error handling is as follows:
The Interdata simulator implements symbolic display and input. Display is
controlled by command line switches:
-a display as ASCII character
-c display as two character string
-a display byte as ASCII character
-c display halfword as two packed ASCII characters
-m display instruction mnemonics
Input parsing is controlled by the first character typed in or by command
@ -855,7 +866,7 @@ line switches:
' or -a ASCII character
" or -c two character sixbit string
alphabetic instruction mnemonic
numeric octal number
numeric hexadecimal number
2.8.1 16b Instruction Input

View file

@ -1,6 +1,6 @@
/* id_dp.c: Interdata 2.5MB/10MB cartridge disk simulator
Copyright (c) 2001-2004, Robert M. Supnik
Copyright (c) 2001-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"),
@ -25,6 +25,7 @@
dp M46-421 2.5MB/10MB cartridge disk
18-Mar-05 RMS Added attached test to detach routine
25-Jan-04 RMS Revised for device debug support
25-Apr-03 RMS Revised for extended file support
16-Feb-03 RMS Fixed read to test transfer ok before selch operation
@ -532,6 +533,7 @@ t_stat dp_detach (UNIT *uptr)
{
uint32 u = uptr - dp_dev.units;
if (!(uptr->flags & UNIT_ATT)) return SCPE_OK; /* attached? */
if (dpd_arm[u]) SET_INT (v_DPC + u + 1); /* if arm, intr */
return detach_unit (uptr);
}

View file

@ -1,6 +1,6 @@
/* id_mt.c: Interdata magnetic tape simulator
Copyright (c) 2001-2004, Robert M Supnik
Copyright (c) 2001-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"),
@ -25,6 +25,7 @@
mt M46-494 dual density 9-track magtape controller
18-Mar-05 RMS Added attached test to detach routine
07-Dec-04 RMS Added read-only file support
25-Apr-03 RMS Revised for extended file support
28-Mar-03 RMS Added multiformat support
@ -445,6 +446,7 @@ t_stat mt_detach (UNIT* uptr)
int32 u = uptr - mt_dev.units;
t_stat r;
if (!(uptr->flags & UNIT_ATT)) return SCPE_OK;
r = sim_tape_detach (uptr);
if (r != SCPE_OK) return r;
if (mt_arm[u]) SET_INT (v_MT + u);

View file

@ -1,6 +1,6 @@
/* nova_mta.c: NOVA magnetic tape simulator
Copyright (c) 1993-2004, 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"),
@ -25,6 +25,7 @@
mta magnetic tape
18-Mar-05 RMS Added attached test to detach routine
22-Nov-03 CEO DIB returns # records skipped after space fwd
22-Nov-03 CEO Removed cancel of tape events in IORST
25-Apr-03 RMS Revised for extended file support
@ -546,6 +547,7 @@ return r;
t_stat mta_detach (UNIT* uptr)
{
if (!(uptr->flags & UNIT_ATT)) return SCPE_OK; /* attached? */
if (!sim_is_active (uptr)) mta_upddsta (uptr, 0);
return sim_tape_detach (uptr);
}

View file

@ -1,6 +1,6 @@
/* pdp10_lp20.c: PDP-10 LP20 line printer simulator
Copyright (c) 1993-2004, 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"),
@ -25,6 +25,7 @@
lp20 line printer
18-Mar-05 RMS Added attached test to detach routine
29-Dec-03 RMS Fixed bug in scheduling
25-Apr-03 RMS Revised for extended file support
29-Sep-02 RMS Added variable vector support
@ -581,6 +582,7 @@ t_stat lp20_detach (UNIT *uptr)
{
t_stat reason;
if (!(uptr->flags & UNIT_ATT)) return SCPE_OK; /* attached? */
reason = detach_unit (uptr);
sim_cancel (&lp20_unit);
lpcsa = lpcsa & ~CSA_GO;

View file

@ -1,6 +1,6 @@
/* pdp10_rp.c - RH11/RP04/05/06/07 RM02/03/05/80 "Massbus" disk controller
Copyright (c) 1993-2004, 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"),
@ -25,6 +25,7 @@
rp RH/RP/RM moving head disks
18-Mar-05 RMS Added attached test to detach routine
20-Sep-04 RMS Fixed bugs in replicated state, RP vs RM accuracy
04-Jan-04 RMS Changed sim_fsize calling sequence
23-Jul-03 RMS Fixed bug in read header stub
@ -1036,6 +1037,7 @@ t_stat rp_detach (UNIT *uptr)
{
int32 drv;
if (!(uptr->flags & UNIT_ATT)) return SCPE_OK; /* attached? */
drv = uptr - rp_dev.units; /* get drv number */
rpds[drv] = (rpds[drv] & ~(DS_MOL | DS_RDY | DS_WRL | DS_VV | DS_OF)) |
DS_ATA;

View file

@ -1,6 +1,6 @@
/* pdp10_tu.c - PDP-10 RH11/TM03/TU45 magnetic tape simulator
Copyright (c) 1993-2004, 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"),
@ -25,6 +25,9 @@
tu RH11/TM03/TU45 magtape
31-Mar-05 RMS Fixed bug, ERASE/WREOF incorrectly clear CS1<done>
Fixed inaccuracies in error reporting
18-Mar-05 RMS Added attached test to detach routine
23-Oct-04 RMS Fixed setting done on non data transfers
01-Oct-04 RMS Modified to set FCE on read short record, eof
Implemented write check
@ -333,7 +336,7 @@ t_stat tu_boot (int32 unitno, DEVICE *dptr);
void tu_go (int32 drv);
void set_tuer (int32 flag);
void update_tucs (int32 flag, int32 drv);
t_stat tu_map_err (UNIT *uptr, t_stat st);
t_stat tu_map_err (UNIT *uptr, t_stat st, t_bool qdt);
/* TU data structures
@ -637,6 +640,21 @@ case FNC_SPACER:
uptr->USTAT = FS_PIP;
goto GO_XFER;
case FNC_WREOF: /* write tape mark */
case FNC_ERASE: /* erase */
if ((uptr->flags & UNIT_ATT) == 0) { /* unattached? */
set_tuer (ER_UNS);
break; }
if (sim_tape_wrp (uptr)) { /* write locked? */
set_tuer (ER_NXF);
break; }
if (fmt_test[GET_FMT (tutc)] == 0) { /* invalid format? */
set_tuer (ER_FER);
break; }
if (uptr->UDENS == UD_UNK) uptr->UDENS = den; /* set dens */
uptr->USTAT = 0;
goto GO_XFER;
case FNC_WCHKR: /* wchk = read */
case FNC_READR: /* read rev */
if (tufs & FS_BOT) { /* beginning of tape? */
@ -649,11 +667,6 @@ case FNC_WRITE: /* write */
((den == TC_800) && (tufc > 0777765))) { /* NRZI, fc < 13? */
set_tuer (ER_NXF);
break; }
case FNC_WREOF: /* write tape mark */
case FNC_ERASE: /* erase */
if (sim_tape_wrp (uptr)) { /* write locked? */
set_tuer (ER_NXF);
break; }
case FNC_WCHKF: /* wchk = read */
case FNC_READF: /* read */
DATA_XFER:
@ -721,7 +734,7 @@ case FNC_SPACEF: /* space forward */
do {
tufc = (tufc + 1) & 0177777; /* incr fc */
if (st = sim_tape_sprecf (uptr, &tbc)) { /* space rec fwd, err? */
r = tu_map_err (uptr, st); /* map error */
r = tu_map_err (uptr, st, 0); /* map error */
break; }
}
while (tufc != 0);
@ -734,7 +747,7 @@ case FNC_SPACER: /* space reverse */
do {
tufc = (tufc + 1) & 0177777; /* incr wc */
if (st = sim_tape_sprecr (uptr, &tbc)) { /* space rec rev, err? */
r = tu_map_err (uptr, st); /* map error */
r = tu_map_err (uptr, st, 0); /* map error */
break; }
}
while (tufc != 0);
@ -745,13 +758,13 @@ case FNC_SPACER: /* space reverse */
case FNC_WREOF: /* write end of file */
if (st = sim_tape_wrtmk (uptr)) /* write tmk, err? */
r = tu_map_err (uptr, st); /* map error */
r = tu_map_err (uptr, st, 0); /* map error */
tufs = tufs | FS_ATA;
break;
case FNC_ERASE:
if (sim_tape_wrp (uptr)) /* write protected? */
r = tu_map_err (uptr, MTSE_WRP); /* map error */
r = tu_map_err (uptr, MTSE_WRP, 0); /* map error */
tufs = tufs | FS_ATA;
break;
@ -775,7 +788,7 @@ case FNC_WCHKF: /* wcheck = read */
tufs = tufs | FS_ID; /* PE BOT? ID burst */
TXFR (ba, wc, 0); /* validate transfer */
if (st = sim_tape_rdrecf (uptr, xbuf, &tbc, MT_MAXFR)) { /* read fwd */
r = tu_map_err (uptr, st); /* map error */
r = tu_map_err (uptr, st, 1); /* map error */
break; } /* done */
for (i = j = 0; (i < wc10) && (j < ((int32) tbc)); i++) {
if ((i == 0) || NEWPAGE (ba10 + i, 0)) { /* map new page */
@ -808,7 +821,7 @@ case FNC_WRITE: /* write */
mpa10 = mpa10 + 1; } /* end for */
if (j < fc) fc = j; /* short record? */
if (st = sim_tape_wrrecf (uptr, xbuf, fc)) /* write rec, err? */
r = tu_map_err (uptr, st); /* map error */
r = tu_map_err (uptr, st, 1); /* map error */
else {
tufc = (tufc + fc) & 0177777;
if (tufc == 0) tutc = tutc & ~TC_FCS;
@ -821,7 +834,7 @@ case FNC_WCHKR: /* wcheck = read */
tufc = 0; /* clear frame count */
TXFR (ba, wc, 1); /* validate xfer rev */
if (st = sim_tape_rdrecr (uptr, xbuf + 4, &tbc, MT_MAXFR)) { /* read rev */
r = tu_map_err (uptr, st); /* map error */
r = tu_map_err (uptr, st, 1); /* map error */
break; } /* done */
for (i = 0; i < 4; i++) xbuf[i] = 0;
for (i = 0, j = tbc + 4; (i < wc10) && (j >= 4); i++) {
@ -907,35 +920,41 @@ return VEC_TU; /* acknowledge */
/* Map tape error status */
t_stat tu_map_err (UNIT *uptr, t_stat st)
t_stat tu_map_err (UNIT *uptr, t_stat st, t_bool qdt)
{
switch (st) {
case MTSE_FMT: /* illegal fmt */
case MTSE_UNATT: /* not attached */
set_tuer (ER_NXF); /* can't execute */
if (qdt) tucs1 = tucs1 | CS1_TRE; /* data xfr? set TRE */
case MTSE_OK: /* no error */
return SCPE_IERR;
case MTSE_TMK: /* end of file */
tufs = tufs | FS_TMK;
set_tuer (ER_FCE); /* also sets FCE */
tufs = tufs | FS_TMK;
break;
case MTSE_IOERR: /* IO error */
set_tuer (ER_VPE); /* flag error */
if (qdt) tucs1 = tucs1 | CS1_TRE; /* data xfr? set TRE */
if (tu_stopioe) return SCPE_IOERR;
break;
case MTSE_INVRL: /* invalid rec lnt */
set_tuer (ER_VPE); /* flag error */
if (qdt) tucs1 = tucs1 | CS1_TRE; /* data xfr? set TRE */
return SCPE_MTRLNT;
case MTSE_RECE: /* record in error */
set_tuer (ER_CRC); /* set crc err */
if (qdt) tucs1 = tucs1 | CS1_TRE; /* data xfr? set TRE */
break;
case MTSE_EOM: /* end of medium */
set_tuer (ER_OPI); /* incomplete */
if (qdt) tucs1 = tucs1 | CS1_TRE; /* data xfr? set TRE */
break;
case MTSE_BOT: /* reverse into BOT */
break;
case MTSE_WRP: /* write protect */
set_tuer (ER_NXF); /* can't execute */
if (qdt) tucs1 = tucs1 | CS1_TRE; /* data xfr? set TRE */
break; }
return SCPE_OK;
}
@ -992,6 +1011,7 @@ t_stat tu_detach (UNIT* uptr)
{
int32 drv = uptr - tu_dev.units;
if (!(uptr->flags & UNIT_ATT)) return SCPE_OK; /* attached? */
if (sim_is_active (uptr)) { /* unit active? */
sim_cancel (uptr); /* cancel operation */
tuer = tuer | ER_UNS; /* set formatter error */

View file

@ -1,6 +1,6 @@
/* pdp11_hk.c - RK611/RK06/RK07 disk controller
Copyright (c) 1993-2004, 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"),
@ -25,6 +25,7 @@
hk RK611/RK06/RK07 disk
18-Mar-05 RMS Added attached test to detach routine
03-Oct-04 RMS Revised Unibus interface
RMS Fixed state of output ready for M+
26-Mar-04 RMS Fixed warnings with -std=c99
@ -1062,6 +1063,7 @@ t_stat hk_detach (UNIT *uptr)
{
int32 drv;
if (!(uptr->flags & UNIT_ATT)) return SCPE_OK; /* attached? */
drv = uptr - hk_dev.units; /* get drv number */
hkds[drv] = (hkds[drv] & ~(DS_RDY | DS_WRL | DS_VV | DS_OF)) | DS_ATA;
if (sim_is_active (uptr)) { /* unit active? */

View file

@ -1,6 +1,6 @@
/* pdp11_rp.c - RP04/05/06/07 RM02/03/05/80 Massbus disk controller
Copyright (c) 1993-2004, 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"),
@ -25,6 +25,7 @@
rp RH/RP/RM moving head disks
18-Mar-05 RMS Added attached test to detach routine
12-Sep-04 RMS Cloned from pdp11_rp.c
Note: The VMS driver and the RP controller documentation state that
@ -922,6 +923,7 @@ t_stat rp_detach (UNIT *uptr)
{
int32 drv;
if (!(uptr->flags & UNIT_ATT)) return SCPE_OK; /* attached? */
drv = uptr - rp_dev.units; /* get drv number */
rpds[drv] = rpds[drv] & ~(DS_MOL | DS_RDY | DS_WRL | DS_VV | DS_OFM);
rp_update_ds (DS_ATA, drv); /* request intr */

View file

@ -537,15 +537,20 @@ int32 l8b, brdisp, wd1, wd2;
extern int32 FPS;
cflag = (uptr == NULL) || (uptr == &cpu_unit);
c1 = val[0] & 0177;
c2 = (val[0] >> 8) & 0177;
if (sw & SWMASK ('A')) { /* ASCII? */
c1 = (val[0] >> ((addr & 1)? 8: 0)) & 0177;
fprintf (of, (c1 < 040)? "<%03o>": "%c", c1);
return SCPE_OK; }
return 0; }
if (sw & SWMASK ('B')) { /* byte? */
c1 = (val[0] >> ((addr & 1)? 8: 0)) & 0377;
fprintf (of, "%o", c1);
return 0; }
if (sw & SWMASK ('C')) { /* character? */
c1 = val[0] & 0177;
c2 = (val[0] >> 8) & 0177;
fprintf (of, (c1 < 040)? "<%03o>": "%c", c1);
fprintf (of, (c2 < 040)? "<%03o>": "%c", c2);
return SCPE_OK; }
return -1; }
if (sw & SWMASK ('R')) { /* radix 50? */
if (val[0] > 0174777) return SCPE_ARG; /* max value */
c3 = val[0] % 050;
@ -553,76 +558,84 @@ if (sw & SWMASK ('R')) { /* radix 50? */
c1 = val[0] / (050 * 050);
fprintf (of, "%c%c%c", r50_to_asc[c1],
r50_to_asc[c2], r50_to_asc[c3]);
return SCPE_OK; }
return -1; }
if (!(sw & SWMASK ('M'))) return SCPE_ARG;
inst = val[0] | ((FPS << (I_V_L - FPS_V_L)) & I_L) |
((FPS << (I_V_D - FPS_V_D)) & I_D); /* inst + fp mode */
for (i = 0; opc_val[i] >= 0; i++) { /* loop thru ops */
j = (opc_val[i] >> I_V_CL) & I_M_CL; /* get class */
if ((opc_val[i] & 0777777) == (inst & masks[j])) { /* match? */
srcm = (inst >> 6) & 077; /* opr fields */
srcr = srcm & 07;
fac = srcm & 03;
dstm = inst & 077;
dstr = dstm & 07;
l8b = inst & 0377;
j = (opc_val[i] >> I_V_CL) & I_M_CL; /* get class */
if ((opc_val[i] & 0777777) == (inst & masks[j])) { /* match? */
srcm = (inst >> 6) & 077; /* opr fields */
srcr = srcm & 07;
fac = srcm & 03;
dstm = inst & 077;
dstr = dstm & 07;
l8b = inst & 0377;
wd1 = wd2 = 0;
/* Instruction decode */
switch (j) { /* case on class */
case I_V_NPN: case I_V_CCC: case I_V_CCS: /* no operands */
switch (j) { /* case on class */
case I_V_NPN: case I_V_CCC: case I_V_CCS: /* no operands */
fprintf (of, "%s", opcode[i]);
return SCPE_OK;
case I_V_REG: /* reg */
break;
case I_V_REG: /* reg */
fprintf (of, "%s %-s", opcode[i], rname[dstr]);
return SCPE_OK;
case I_V_SOP: /* sop */
break;
case I_V_SOP: /* sop */
fprintf (of, "%s ", opcode[i]);
return fprint_spec (of, addr, dstm, val[1], cflag, TRUE);
case I_V_3B: /* 3b */
wd1 = fprint_spec (of, addr, dstm, val[1], cflag, TRUE);
break;
case I_V_3B: /* 3b */
fprintf (of, "%s %-o", opcode[i], dstr);
return SCPE_OK;
case I_V_FOP: /* fop */
break;
case I_V_FOP: /* fop */
fprintf (of, "%s ", opcode[i]);
return fprint_spec (of, addr, dstm, val[1], cflag, FALSE);
case I_V_AFOP: /* afop */
wd1 = fprint_spec (of, addr, dstm, val[1], cflag, FALSE);
break;
case I_V_AFOP: /* afop */
fprintf (of, "%s %s,", opcode[i], fname[fac]);
return fprint_spec (of, addr, dstm, val[1], cflag, FALSE);
case I_V_6B: /* 6b */
wd1 = fprint_spec (of, addr, dstm, val[1], cflag, FALSE);
break;
case I_V_6B: /* 6b */
fprintf (of, "%s %-o", opcode[i], dstm);
return SCPE_OK;
case I_V_BR: /* cond branch */
break;
case I_V_BR: /* cond branch */
fprintf (of, "%s ", opcode[i]);
brdisp = (l8b + l8b + ((l8b & 0200)? 0177002: 2)) & 0177777;
if (cflag) fprintf (of, "%-o", (addr + brdisp) & 0177777);
else if (brdisp < 01000) fprintf (of, ".+%-o", brdisp);
else fprintf (of, ".-%-o", 0200000 - brdisp);
return SCPE_OK;
case I_V_8B: /* 8b */
break;
case I_V_8B: /* 8b */
fprintf (of, "%s %-o", opcode[i], l8b);
return SCPE_OK;
case I_V_SOB: /* sob */
break;
case I_V_SOB: /* sob */
fprintf (of, "%s %s,", opcode[i], rname[srcr]);
brdisp = (dstm * 2) - 2;
if (cflag) fprintf (of, "%-o", (addr - brdisp) & 0177777);
else if (brdisp <= 0) fprintf (of, ".+%-o", -brdisp);
else fprintf (of, ".-%-o", brdisp);
return SCPE_OK;
case I_V_RSOP: /* rsop */
break;
case I_V_RSOP: /* rsop */
fprintf (of, "%s %s,", opcode[i], rname[srcr]);
return fprint_spec (of, addr, dstm, val[1], cflag, TRUE);
case I_V_ASOP: case I_V_ASMD: /* asop, asmd */
wd1 = fprint_spec (of, addr, dstm, val[1], cflag, TRUE);
break;
case I_V_ASOP: case I_V_ASMD: /* asop, asmd */
fprintf (of, "%s %s,", opcode[i], fname[fac]);
return fprint_spec (of, addr, dstm, val[1], cflag, TRUE);
case I_V_DOP: /* dop */
wd1 = fprint_spec (of, addr, dstm, val[1], cflag, TRUE);
break;
case I_V_DOP: /* dop */
fprintf (of, "%s ", opcode[i]);
wd1 = fprint_spec (of, addr, srcm, val[1], cflag, TRUE);
fprintf (of, ",");
wd2 = fprint_spec (of, addr - wd1 - wd1, dstm,
val[1 - wd1], cflag, TRUE);
return wd1 + wd2; } /* end case */
} /* end if */
val[1 - wd1], cflag, TRUE);
break;
} /* end case */
return ((wd1 + wd2) * 2) - 1;
} /* end if */
} /* end for */
return SCPE_ARG; /* no match */
}
@ -807,6 +820,7 @@ default:
t_stat parse_sym (char *cptr, t_addr addr, UNIT *uptr, t_value *val, int32 sw)
{
int32 cflag, d, i, j, reg, spec, n1, n2, disp, pflag;
t_value by;
t_stat r;
char *tptr, gbuf[CBUFSIZE];
@ -814,12 +828,19 @@ cflag = (uptr == NULL) || (uptr == &cpu_unit);
while (isspace (*cptr)) cptr++; /* absorb spaces */
if ((sw & SWMASK ('A')) || ((*cptr == '\'') && cptr++)) { /* ASCII char? */
if (cptr[0] == 0) return SCPE_ARG; /* must have 1 char */
val[0] = (t_value) cptr[0];
return SCPE_OK; }
if (addr & 1) val[0] = (val[0] & 0377) | (((t_value) cptr[0]) << 8);
else val[0] = (val[0] & ~0377) | ((t_value) cptr[0]);
return 0; }
if (sw & SWMASK ('B')) { /* byte? */
by = get_uint (cptr, 8, 0377, &r); /* get byte */
if (r != SCPE_OK) return SCPE_ARG;
if (addr & 1) val[0] = (val[0] & 0377) | (by << 8);
else val[0] = (val[0] & ~0377) | by;
return 0; }
if ((sw & SWMASK ('C')) || ((*cptr == '"') && cptr++)) { /* ASCII string? */
if (cptr[0] == 0) return SCPE_ARG; /* must have 1 char */
val[0] = ((t_value) cptr[1] << 8) + (t_value) cptr[0];
return SCPE_OK; }
val[0] = ((t_value) cptr[1] << 8) | (t_value) cptr[0];
return -1; }
if (sw & SWMASK ('R')) return SCPE_ARG; /* radix 50 */
cptr = get_glyph (cptr, gbuf, 0); /* get opcode */
@ -909,5 +930,5 @@ case I_V_CCC: case I_V_CCS: /* cond code oper */
default:
return SCPE_ARG; }
if (*cptr != 0) return SCPE_ARG; /* junk at end? */
return n1 + n2;
return ((n1 + n2) * 2) - 1;
}

View file

@ -1,6 +1,6 @@
/* pdp11_tm.c: PDP-11 magnetic tape simulator
Copyright (c) 1993-2004, 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"),
@ -25,6 +25,7 @@
tm TM11/TU10 magtape
18-Mar-05 RMS Added attached test to detach routine
07-Dec-04 RMS Added read-only file support
30-Sep-04 RMS Revised Unibus interface
25-Jan-04 RMS Revised for device debug support
@ -557,6 +558,7 @@ t_stat tm_detach (UNIT* uptr)
{
int32 u = uptr - tm_dev.units;
if (!(uptr->flags & UNIT_ATT)) return SCPE_OK;
if (!sim_is_active (uptr)) uptr->USTAT = 0;
if (u == GET_UNIT (tm_cmd)) tm_updcsta (uptr);
return sim_tape_detach (uptr);

View file

@ -47,7 +47,7 @@
#elif defined (VM_VAX) /* VAX version */
#include "vax_defs.h"
#if (UNIBUS)
#define INIT_TYPE TQU_TYPE
#define INIT_TYPE TQ8_TYPE
#else
#define INIT_TYPE TQ5_TYPE
#endif
@ -1755,7 +1755,6 @@ return SCPE_OK;
#define BOOT_CSR (BOOT_START + 014) /* CSR */
#define BOOT_LEN (sizeof (boot_rom) / sizeof (int16))
/* Data structure definitions */
#define B_CMDINT (BOOT_START - 01000) /* cmd int */

View file

@ -1,6 +1,6 @@
/* pdp11_ts.c: TS11/TSV05 magnetic tape simulator
Copyright (c) 1993-2004, 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"),
@ -25,6 +25,7 @@
ts TS11/TSV05 magtape
18-Mar-05 RMS Added attached test to detach routine
07-Dec-04 RMS Added read-only file support
30-Sep-04 RMS Revised Unibus interface
25-Jan-04 RMS Revised for device debug support
@ -935,6 +936,7 @@ t_stat ts_detach (UNIT* uptr)
{
t_stat r;
if (!(uptr->flags & UNIT_ATT)) return SCPE_OK; /* attached? */
r = sim_tape_detach (uptr); /* detach unit */
if (r != SCPE_OK) return r; /* error? */
tssr = tssr | TSSR_OFL; /* set offline */

View file

@ -1,6 +1,6 @@
/* pdp11_tu.c - PDP-11 TM02/TU16 TM03/TU45/TU77 Massbus magnetic tape controller
Copyright (c) 1993-2004, 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"),
@ -25,6 +25,8 @@
tu TM02/TM03 magtape
31-Mar-05 RMS Fixed inaccuracies in error reporting
18-Mar-05 RMS Added attached test to detach routine
10-Sep-04 RMS Cloned from pdp10_tu.c
Magnetic tapes are represented as a series of variable 8b records
@ -246,7 +248,7 @@ int32 tu_abort (void);
void tu_set_er (int32 flg);
void tu_clr_as (int32 mask);
void tu_update_fs (int32 flg, int32 drv);
t_stat tu_map_err (int32 drv, t_stat st);
t_stat tu_map_err (int32 drv, t_stat st, t_bool qdt);
/* TU data structures
@ -569,7 +571,7 @@ case FNC_SPACEF: /* space forward */
do {
tufc = (tufc + 1) & 0177777; /* incr fc */
if (st = sim_tape_sprecf (uptr, &tbc)) { /* space rec fwd, err? */
r = tu_map_err (drv, st); /* map error */
r = tu_map_err (drv, st, 0); /* map error */
break; }
}
while (tufc != 0);
@ -581,7 +583,7 @@ case FNC_SPACER: /* space reverse */
do {
tufc = (tufc + 1) & 0177777; /* incr wc */
if (st = sim_tape_sprecr (uptr, &tbc)) { /* space rec rev, err? */
r = tu_map_err (drv, st); /* map error */
r = tu_map_err (drv, st, 0); /* map error */
break; }
}
while (tufc != 0);
@ -591,12 +593,12 @@ case FNC_SPACER: /* space reverse */
case FNC_WREOF: /* write end of file */
if (st = sim_tape_wrtmk (uptr)) /* write tmk, err? */
r = tu_map_err (drv, st); /* map error */
r = tu_map_err (drv, st, 0); /* map error */
break;
case FNC_ERASE:
if (sim_tape_wrp (uptr)) /* write protected? */
r = tu_map_err (drv, MTSE_WRP); /* map error */
r = tu_map_err (drv, MTSE_WRP, 0); /* map error */
break;
/* Unit service - data transfer commands */
@ -607,7 +609,7 @@ case FNC_WCHKF: /* wcheck = read */
if ((uptr->UDENS == TC_1600) && sim_tape_bot (uptr))
tufs = tufs | FS_ID; /* PE BOT? ID burst */
if (st = sim_tape_rdrecf (uptr, xbuf, &tbc, MT_MAXFR)) { /* read fwd */
r = tu_map_err (drv, st); /* map error */
r = tu_map_err (drv, st, 1); /* map error */
break; } /* done */
for (i = tbc; i < tbc + 4; i++) xbuf[i] = 0; /* pad with 0's */
if (fmt == TC_CDUMP) { /* core dump? */
@ -652,7 +654,7 @@ case FNC_WRITE: /* write */
tbc = xbc;
}
if (st = sim_tape_wrrecf (uptr, xbuf, tbc)) /* write rec, err? */
r = tu_map_err (drv, st); /* map error */
r = tu_map_err (drv, st, 1); /* map error */
else {
tufc = (tufc + tbc) & 0177777;
if (tufc == 0) tutc = tutc & ~TC_FCS;
@ -663,7 +665,7 @@ case FNC_READR: /* read reverse */
case FNC_WCHKR: /* wcheck = read */
tufc = 0; /* clear frame count */
if (st = sim_tape_rdrecr (uptr, xbuf + 4, &tbc, MT_MAXFR)) { /* read rev */
r = tu_map_err (drv, st); /* map error */
r = tu_map_err (drv, st, 1); /* map error */
break; } /* done */
for (i = 0; i < 4; i++) xbuf[i] = 0; /* pad with 0's */
if (fmt == TC_CDUMP) { /* core dump? */
@ -740,12 +742,13 @@ return;
/* Map tape error status */
t_stat tu_map_err (int32 drv, t_stat st)
t_stat tu_map_err (int32 drv, t_stat st, t_bool qdt)
{
switch (st) {
case MTSE_FMT: /* illegal fmt */
case MTSE_UNATT: /* not attached */
tu_set_er (ER_NXF); /* can't execute */
if (qdt) mba_set_exc (tu_dib.ba); /* set exception */
break;
case MTSE_TMK: /* end of file */
tufs = tufs | FS_TMK;
@ -753,21 +756,25 @@ case MTSE_TMK: /* end of file */
break;
case MTSE_IOERR: /* IO error */
tu_set_er (ER_VPE); /* flag error */
mba_set_exc (tu_dib.ba); /* set exception */
if (qdt) mba_set_exc (tu_dib.ba); /* set exception */
return (tu_stopioe? SCPE_IOERR: SCPE_OK);
case MTSE_INVRL: /* invalid rec lnt */
tu_set_er (ER_VPE); /* flag error */
if (qdt) mba_set_exc (tu_dib.ba); /* set exception */
return SCPE_MTRLNT;
case MTSE_RECE: /* record in error */
tu_set_er (ER_CRC); /* set crc err */
if (qdt) mba_set_exc (tu_dib.ba); /* set exception */
break;
case MTSE_EOM: /* end of medium */
tu_set_er (ER_OPI); /* incomplete */
if (qdt) mba_set_exc (tu_dib.ba); /* set exception */
break;
case MTSE_BOT: /* reverse into BOT */
return SCPE_OK;
case MTSE_WRP: /* write protect */
tu_set_er (ER_NXF); /* can't execute */
if (qdt) mba_set_exc (tu_dib.ba); /* set exception */
break;
default: /* unknown error */
return SCPE_IERR; }
@ -822,6 +829,7 @@ t_stat tu_detach (UNIT* uptr)
{
int32 drv = uptr - tu_dev.units;
if (!(uptr->flags & UNIT_ATT)) return SCPE_OK; /* attached? */
uptr->USTAT = 0; /* clear status flags */
tu_update_fs (FS_ATA | FS_SSC, drv); /* update status */
return sim_tape_detach (uptr);

View file

@ -1,7 +1,7 @@
/* pdp11_xu.c: DEUNA/DELUA ethernet controller simulator
------------------------------------------------------------------------------
Copyright (c) 2003-2004, David T. Hittner
Copyright (c) 2003-2005, David T. Hittner
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
@ -52,6 +52,7 @@
Modification history:
10-Mar-05 RMS Fixed equality test in RCSTAT (from Mark Hittinger)
16-Jan-04 DTH Added more info to SHOW MOD commands
09-Jan-04 DTH Made XU floating address so that XUB will float correctly
08-Jan-04 DTH Added system_id message
@ -783,7 +784,7 @@ int32 xu_command(CTLR* xu)
if ((wstatus != SCPE_OK) || (wstatus2 != SCPE_OK) || (wstatus3 != SCPE_OK))
return PCSR0_PCEI + 1;
if (fnc = FC_RCSTAT)
if (fnc == FC_RCSTAT)
xu->var->stat &= 0377; /* clear high byte */
break;

View file

@ -1,6 +1,6 @@
/* pdp18b_mt.c: 18b PDP magnetic tape simulator
Copyright (c) 1993-2004, 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"),
@ -26,6 +26,7 @@
mt (PDP-9) TC59 magtape
(PDP-15) TC59D magtape
18-Mar-05 RMS Added attached test to detach routine
14-Jan-04 RMS Revised IO device call interface
25-Apr-03 RMS Revised for extended file support
28-Mar-03 RMS Added multiformat support
@ -471,6 +472,7 @@ return r;
t_stat mt_detach (UNIT* uptr)
{
if (!(uptr->flags & UNIT_ATT)) return SCPE_OK; /* attached? */
if (!sim_is_active (uptr)) uptr->USTAT = 0;
mt_updcsta (mt_dev.units + GET_UNIT (mt_cu), 0); /* update status */
return sim_tape_detach (uptr);

View file

@ -1,6 +1,6 @@
/* pdp8_mt.c: PDP-8 magnetic tape simulator
Copyright (c) 1993-2004, 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"),
@ -25,6 +25,7 @@
mt TM8E/TU10 magtape
18-Mar-05 RMS Added attached test to detach routine
25-Apr-03 RMS Revised for extended file support
29-Mar-03 RMS Added multiformat support
04-Mar-03 RMS Fixed bug in SKTR
@ -563,6 +564,7 @@ t_stat mt_detach (UNIT* uptr)
{
int32 u = uptr - mt_dev.units; /* get unit number */
if (!(uptr->flags & UNIT_ATT)) return SCPE_OK; /* check for attached */
if (!sim_is_active (uptr)) uptr->USTAT = STA_REM;
if (u == GET_UNIT (mt_cu)) mt_updcsta (uptr);
return sim_tape_detach (uptr);

View file

@ -1,403 +0,0 @@
/* vax780_defs.h: VAX 780 model-specific definitions file
Copyright (c) 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 file covers the VAX 11/780, the first VAX.
System memory map
0000 0000 - 1FFF FFFF main memory
2000 0000 - 2001 FFFF nexus register space
2002 0000 - 200F FFFF reserved
2010 0000 - 2013 FFFF Unibus address space, Unibus 0
2014 0000 - 2017 FFFF Unibus address space, Unibus 1
2018 0000 - 201B FFFF Unibus address space, Unibus 2
201C 0000 - 201F FFFF Unibus address space, Unibus 3
2020 0000 - 3FFF FFFF reserved
*/
/* Microcode constructs */
#ifndef FULL_VAX
#define FULL_VAX 1
#endif
#ifndef _VAX_780_DEFS_H_
#define _VAX_780_DEFS_H_ 1
#define VAX780_SID (1 << 24) /* system ID */
#define VAX780_ECO (7 << 19) /* ucode revision */
#define VAX780_PLANT (0 << 12) /* plant (Salem NH) */
#define VAX780_SN (1234)
#define CON_HLTPIN 0x0200 /* external CPU halt */
#define CON_HLTINS 0x0600 /* HALT instruction */
#define MCHK_RD_F 0x00 /* read fault */
#define MCHK_RD_A 0xF4 /* read abort */
#define MCHK_IBUF 0x0D /* read istream */
/* Interrupts */
#define IPL_HMAX 0x17 /* highest hwre level */
#define IPL_HMIN 0x14 /* lowest hwre level */
#define IPL_HLVL (IPL_HMAX - IPL_HMIN + 1) /* # hardware levels */
#define IPL_SMAX 0xF /* highest swre level */
/* Nexus constants */
#define NEXUS_NUM 16 /* number of nexus */
#define MCTL_NUM 2 /* number of mem ctrl */
#define MBA_NUM 2 /* number of MBA's */
#define TR_MCTL0 1 /* nexus assignments */
#define TR_MCTL1 2
#define TR_UBA 3
#define TR_MBA0 8
#define TR_MBA1 9
#define NEXUS_HLVL (IPL_HMAX - IPL_HMIN + 1)
#define SCB_NEXUS 0x100 /* nexus intr base */
#define SBI_FAULTS 0xFC000000 /* SBI fault flags */
/* Internal I/O interrupts - relative except for clock and console */
#define IPL_CLKINT 0x18 /* clock IPL */
#define IPL_TTINT 0x14 /* console IPL */
#define IPL_MCTL0 (0x15 - IPL_HMIN)
#define IPL_MCTL1 (0x15 - IPL_HMIN)
#define IPL_UBA (0x15 - IPL_HMIN)
#define IPL_MBA0 (0x15 - IPL_HMIN)
#define IPL_MBA1 (0x15 - IPL_HMIN)
/* Nexus interrupt macros */
#define SET_NEXUS_INT(dv) nexus_req[IPL_##dv] |= (1 << TR_##dv)
#define CLR_NEXUS_INT(dv) nexus_req[IPL_##dv] &= ~(1 << TR_##dv)
/* Machine specific IPRs */
#define MT_ACCS 40 /* FPA control */
#define MT_ACCR 41 /* FPA maint */
#define MT_WCSA 44 /* WCS address */
#define MT_WCSD 45 /* WCS data */
#define MT_SBIFS 48 /* SBI fault status */
#define MT_SBIS 49 /* SBI silo */
#define MT_SBISC 50 /* SBI silo comparator */
#define MT_SBIMT 51 /* SBI maint */
#define MT_SBIER 52 /* SBI error */
#define MT_SBITA 53 /* SBI timeout addr */
#define MT_SBIQC 54 /* SBI timeout clear */
#define MT_MBRK 60 /* microbreak */
/* Memory */
#define MAXMEMWIDTH 23 /* max mem, MS780C */
#define MAXMEMSIZE (1 << MAXMEMWIDTH)
#define MAXMEMWIDTH_X 27 /* max mem, MS780E */
#define MAXMEMSIZE_X (1 << MAXMEMWIDTH_X)
#define INITMEMSIZE (1 << MAXMEMWIDTH) /* initial memory size */
#define MEMSIZE (cpu_unit.capac)
#define ADDR_IS_MEM(x) (((uint32) (x)) < MEMSIZE)
/* Unibus I/O registers */
#define UBADDRWIDTH 18 /* Unibus addr width */
#define UBADDRSIZE (1u << UBADDRWIDTH) /* Unibus addr length */
#define UBADDRMASK (UBADDRSIZE - 1) /* Unibus addr mask */
#define IOPAGEAWIDTH 13 /* IO addr width */
#define IOPAGESIZE (1u << IOPAGEAWIDTH) /* IO page length */
#define IOPAGEMASK (IOPAGESIZE - 1) /* IO addr mask */
#define UBADDRBASE 0x20100000 /* Unibus addr base */
#define IOPAGEBASE 0x2013E000 /* IO page base */
#define ADDR_IS_IO(x) ((((uint32) (x)) >= UBADDRBASE) && \
(((uint32) (x)) < (UBADDRBASE + UBADDRSIZE)))
#define ADDR_IS_IOP(x) (((uint32) (x)) >= IOPAGEBASE)
/* Nexus register space */
#define REGAWIDTH 17 /* REG addr width */
#define REG_V_NEXUS 13 /* nexus number */
#define REG_M_NEXUS 0xF
#define REG_V_OFS 2 /* register number */
#define REG_M_OFS 0x7FF
#define REGSIZE (1u << REGAWIDTH) /* REG length */
#define REGBASE 0x20000000 /* REG addr base */
#define ADDR_IS_REG(x) ((((uint32) (x)) >= REGBASE) && \
(((uint32) (x)) < (REGBASE + REGSIZE)))
#define NEXUS_GETNEX(x) (((x) >> REG_V_NEXUS) & REG_M_NEXUS)
#define NEXUS_GETOFS(x) (((x) >> REG_V_OFS) & REG_M_OFS)
/* ROM address space in memory controllers */
#define ROMAWIDTH 12 /* ROM addr width */
#define ROMSIZE (1u << ROMAWIDTH) /* ROM size */
#define ROM0BASE (REGBASE + (TR_MCTL0 << REG_V_NEXUS) + 0x1000)
#define ROM1BASE (REGBASE + (TR_MCTL1 << REG_V_NEXUS) + 0x1000)
#define ADDR_IS_ROM0(x) ((((uint32) (x)) >= ROM0BASE) && \
(((uint32) (x)) < (ROM0BASE + ROMSIZE)))
#define ADDR_IS_ROM1(x) ((((uint32) (x)) >= ROM1BASE) && \
(((uint32) (x)) < (ROM1BASE + ROMSIZE)))
#define ADDR_IS_ROM(x) (ADDR_IS_ROM0 (x) || ADDR_IS_ROM1 (x))
/* Other address spaces */
#define ADDR_IS_CDG(x) (0)
#define ADDR_IS_NVR(x) (0)
/* Unibus I/O modes */
#define READ 0 /* PDP-11 compatibility */
#define WRITE (L_WORD)
#define WRITEB (L_BYTE)
/* Common CSI flags */
#define CSR_V_GO 0 /* go */
#define CSR_V_IE 6 /* interrupt enable */
#define CSR_V_DONE 7 /* done */
#define CSR_V_BUSY 11 /* busy */
#define CSR_V_ERR 15 /* error */
#define CSR_GO (1u << CSR_V_GO)
#define CSR_IE (1u << CSR_V_IE)
#define CSR_DONE (1u << CSR_V_DONE)
#define CSR_BUSY (1u << CSR_V_BUSY)
#define CSR_ERR (1u << CSR_V_ERR)
/* Timers */
#define TMR_CLK 0 /* 100Hz clock */
/* I/O system definitions */
#define DZ_MUXES 4 /* max # of DZV muxes */
#define DZ_LINES 8 /* lines per DZV mux */
#define VH_MUXES 4 /* max # of DHQ muxes */
#define MT_MAXFR (1 << 16) /* magtape max rec */
#define AUTO_LNT 34 /* autoconfig ranks */
#define DEV_V_UBUS (DEV_V_UF + 0) /* Unibus */
#define DEV_V_MBUS (DEV_V_UF + 1) /* Massbus */
#define DEV_V_NEXUS (DEV_V_UF + 2) /* Nexus */
#define DEV_V_FLTA (DEV_V_UF + 3) /* flt addr */
#define DEV_V_FFUF (DEV_V_UF + 4) /* first free flag */
#define DEV_UBUS (1u << DEV_V_UBUS)
#define DEV_MBUS (1u << DEV_V_MBUS)
#define DEV_NEXUS (1u << DEV_V_NEXUS)
#define DEV_FLTA (1u << DEV_V_FLTA)
#define DEV_QBUS (0)
#define DEV_Q18 (0)
#define UNIBUS TRUE /* Unibus only */
#define DEV_RDX 16 /* default device radix */
/* Device information block
For Massbus devices,
ba = Massbus number
lnt = Massbus ctrl type
ack[0] = abort routine
For Nexus devices,
ba = Nexus number
lnt = number of consecutive nexi */
#define VEC_DEVMAX 4 /* max device vec */
struct pdp_dib {
uint32 ba; /* base addr */
uint32 lnt; /* length */
t_stat (*rd)(int32 *dat, int32 ad, int32 md);
t_stat (*wr)(int32 dat, int32 ad, int32 md);
int32 vnum; /* vectors: number */
int32 vloc; /* locator */
int32 vec; /* value */
int32 (*ack[VEC_DEVMAX])(void); /* ack routine */
};
typedef struct pdp_dib DIB;
/* Unibus I/O page layout - XUB,RQB,RQC,RQD float based on number of DZ's
Massbus devices (RP, TU) do not appear in the Unibus IO page */
#define IOBA_DZ (IOPAGEBASE + 000100) /* DZ11 */
#define IOLN_DZ 010
#define IOBA_XUB (IOPAGEBASE + 000330 + (020 * (DZ_MUXES / 2)))
#define IOLN_XUB 010
#define IOBA_RQB (IOPAGEBASE + 000334 + (020 * (DZ_MUXES / 2)))
#define IOLN_RQB 004
#define IOBA_RQC (IOPAGEBASE + IOBA_RQB + IOLN_RQB)
#define IOLN_RQC 004
#define IOBA_RQD (IOPAGEBASE + IOBA_RQC + IOLN_RQC)
#define IOLN_RQD 004
#define IOBA_RQ (IOPAGEBASE + 012150) /* UDA50 */
#define IOLN_RQ 004
#define IOBA_TS (IOPAGEBASE + 012520) /* TS11 */
#define IOLN_TS 004
#define IOBA_RL (IOPAGEBASE + 014400) /* RL11 */
#define IOLN_RL 012
#define IOBA_TQ (IOPAGEBASE + 014500) /* TMSCP */
#define IOLN_TQ 004
#define IOBA_XU (IOPAGEBASE + 014510) /* DEUNA/DELUA */
#define IOLN_XU 010
#define IOBA_RX (IOPAGEBASE + 017170) /* RX11 */
#define IOLN_RX 004
#define IOBA_RY (IOPAGEBASE + 017170) /* RXV21 */
#define IOLN_RY 004
#define IOBA_HK (IOPAGEBASE + 017440) /* RK611 */
#define IOLN_HK 040
#define IOBA_LPT (IOPAGEBASE + 017514) /* LP11 */
#define IOLN_LPT 004
#define IOBA_PTR (IOPAGEBASE + 017550) /* PC11 reader */
#define IOLN_PTR 004
#define IOBA_PTP (IOPAGEBASE + 017554) /* PC11 punch */
#define IOLN_PTP 004
/* Interrupt assignments; within each level, priority is right to left */
#define INT_V_DZRX 0 /* BR5 */
#define INT_V_DZTX 1
#define INT_V_HK 2
#define INT_V_RL 3
#define INT_V_RQ 4
#define INT_V_TQ 5
#define INT_V_TS 6
#define INT_V_RY 7
#define INT_V_XU 8
#define INT_V_LPT 0 /* BR4 */
#define INT_V_PTR 1
#define INT_V_PTP 2
#define INT_DZRX (1u << INT_V_DZRX)
#define INT_DZTX (1u << INT_V_DZTX)
#define INT_HK (1u << INT_V_HK)
#define INT_RL (1u << INT_V_RL)
#define INT_RQ (1u << INT_V_RQ)
#define INT_TQ (1u << INT_V_TQ)
#define INT_TS (1u << INT_V_TS)
#define INT_RY (1u << INT_V_RY)
#define INT_XU (1u << INT_V_XU)
#define INT_PTR (1u << INT_V_PTR)
#define INT_PTP (1u << INT_V_PTP)
#define INT_LPT (1u << INT_V_LPT)
#define IPL_DZRX (0x15 - IPL_HMIN)
#define IPL_DZTX (0x15 - IPL_HMIN)
#define IPL_HK (0x15 - IPL_HMIN)
#define IPL_RL (0x15 - IPL_HMIN)
#define IPL_RQ (0x15 - IPL_HMIN)
#define IPL_TQ (0x15 - IPL_HMIN)
#define IPL_TS (0x15 - IPL_HMIN)
#define IPL_RY (0x15 - IPL_HMIN)
#define IPL_XU (0x15 - IPL_HMIN)
#define IPL_PTR (0x14 - IPL_HMIN)
#define IPL_PTP (0x14 - IPL_HMIN)
#define IPL_LPT (0x14 - IPL_HMIN)
/* Device vectors */
#define VEC_Q 0000
#define VEC_PTR 0070
#define VEC_PTP 0074
#define VEC_XU 0120
#define VEC_RQ 0154
#define VEC_RL 0160
#define VEC_LPT 0200
#define VEC_HK 0210
#define VEC_TS 0224
#define VEC_TQ 0260
#define VEC_RX 0264
#define VEC_RY 0264
#define VEC_DZRX 0300
#define VEC_DZTX 0304
/* Autoconfigure ranks */
#define RANK_DZ 8
#define RANK_RL 14
#define RANK_RX 18
#define RANK_XU 25
#define RANK_RQ 26
#define RANK_TQ 30
#define RANK_VH 32
/* Interrupt macros */
#define IVCL(dv) ((IPL_##dv * 32) + INT_V_##dv)
#define NVCL(dv) ((IPL_##dv * 32) + TR_##dv)
#define IREQ(dv) int_req[IPL_##dv]
#define SET_INT(dv) int_req[IPL_##dv] = int_req[IPL_##dv] | (INT_##dv)
#define CLR_INT(dv) int_req[IPL_##dv] = int_req[IPL_##dv] & ~(INT_##dv)
#define IORETURN(f,v) ((f)? (v): SCPE_OK) /* cond error return */
/* Logging */
#define LOG_CPU_I 0x1 /* intexc */
#define LOG_CPU_R 0x2 /* REI */
#define LOG_CPU_P 0x4 /* context */
/* Massbus definitions */
#define MBA_RP (TR_MBA0 - TR_MBA0) /* MBA for RP */
#define MBA_TU (TR_MBA1 - TR_MBA0) /* MBA for TU */
#define MBA_RMASK 0x1F /* max 32 reg */
#define MBE_NXD 1 /* nx drive */
#define MBE_NXR 2 /* nx reg */
#define MBE_GOE 3 /* err on GO */
/* Boot definitions */
#define BOOT_MB 0 /* device codes */
#define BOOT_HK 1 /* for VMB */
#define BOOT_RL 2
#define BOOT_UDA 17
#define BOOT_TK 18
/* Function prototypes for I/O */
t_bool map_addr (uint32 qa, uint32 *ma);
int32 Map_ReadB (uint32 ba, int32 bc, uint8 *buf);
int32 Map_ReadW (uint32 ba, int32 bc, uint16 *buf);
int32 Map_WriteB (uint32 ba, int32 bc, uint8 *buf);
int32 Map_WriteW (uint32 ba, int32 bc, uint16 *buf);
t_stat set_addr (UNIT *uptr, int32 val, char *cptr, void *desc);
t_stat show_addr (FILE *st, UNIT *uptr, int32 val, void *desc);
t_stat set_addr_flt (UNIT *uptr, int32 val, char *cptr, void *desc);
t_stat set_vec (UNIT *uptr, int32 val, char *cptr, void *desc);
t_stat show_vec (FILE *st, UNIT *uptr, int32 val, void *desc);
t_stat auto_config (uint32 rank, uint32 num);
int32 mba_rdbufW (uint32 mbus, int32 bc, uint16 *buf);
int32 mba_wrbufW (uint32 mbus, int32 bc, uint16 *buf);
int32 mba_chbufW (uint32 mbus, int32 bc, uint16 *buf);
int32 mba_get_bc (uint32 mbus);
void mba_upd_ata (uint32 mbus, uint32 val);
void mba_set_exc (uint32 mbus);
void mba_set_don (uint32 mbus);
t_stat mba_show_num (FILE *st, UNIT *uptr, int32 val, void *desc);
t_stat show_nexus (FILE *st, UNIT *uptr, int32 val, void *desc);
#endif

File diff suppressed because it is too large Load diff

View file

@ -1,696 +0,0 @@
/* vax780_mba.c: VAX 11/780 Massbus adapter
Copyright (c) 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.
mba0, mba1 RH780 Massbus adapter
*/
#include "vax_defs.h"
/* Massbus */
#define MBA_NMAPR 256 /* number of map reg */
#define MBA_V_RTYPE 10 /* nexus addr: reg type */
#define MBA_M_RTYPE 0x3
#define MBART_INT 0x0 /* internal */
#define MBART_EXT 0x1 /* external */
#define MBART_MAP 0x2 /* map */
#define MBA_V_INTOFS 2 /* int reg: reg ofs */
#define MBA_M_INTOFS 0xFF
#define MBA_V_DRV 7 /* ext reg: drive num */
#define MBA_M_DRV 0x7
#define MBA_V_DEVOFS 2 /* ext reg: reg ofs */
#define MBA_M_DEVOFS 0x1F
#define MBA_RTYPE(x) (((x) >> MBA_V_RTYPE) & MBA_M_RTYPE)
#define MBA_INTOFS(x) (((x) >> MBA_V_INTOFS) & MBA_M_INTOFS)
#define MBA_EXTDRV(x) (((x) >> MBA_V_DRV) & MBA_M_DRV)
#define MBA_EXTOFS(x) (((x) >> MBA_V_DEVOFS) & MBA_M_DEVOFS)
/* Massbus configuration register */
#define MBACNF_OF 0x0
#define MBACNF_ADPDN 0x00800000 /* adap pdn - ni */
#define MBACNF_ADPUP 0x00400000 /* adap pup - ni */
#define MBACNF_CODE 0x00000020
#define MBACNF_RD (SBI_FAULTS|MBACNF_W1C)
#define MBACNF_W1C 0x00C00000
/* Control register */
#define MBACR_OF 0x1
#define MBACR_MNT 0x00000008 /* maint */
#define MBACR_IE 0x00000004 /* int enable */
#define MBACR_ABORT 0x00000002 /* abort */
#define MBACR_INIT 0x00000001
#define MBACR_RD 0x0000000E
#define MBACR_WR 0x0000000E
/* Status register */
#define MBASR_OF 0x2
#define MBASR_DTBUSY 0x80000000 /* DT busy RO */
#define MBASR_NRCONF 0x40000000 /* no conf - ni W1C */
#define MBASR_CRD 0x20000000 /* CRD - ni W1C */
#define MBASR_CBH 0x00800000 /* CBHUNG - ni W1C */
#define MBASR_PGE 0x00080000 /* prog err - W1C int */
#define MBASR_NFD 0x00040000 /* nx drive - W1C int */
#define MBASR_MCPE 0x00020000 /* ctl perr - ni W1C int */
#define MBASR_ATA 0x00010000 /* attn - W1C int */
#define MBASR_SPE 0x00004000 /* silo perr - ni W1C int */
#define MBASR_DTCMP 0x00002000 /* xfr done - W1C int */
#define MBASR_DTABT 0x00001000 /* abort - W1C int */
#define MBASR_DLT 0x00000800 /* dat late - ni W1C abt */
#define MBASR_WCEU 0x00000400 /* wrchk upper - W1C abt */
#define MBASR_WCEL 0x00000200 /* wrchk lower - W1C abt */
#define MBASR_MXF 0x00000100 /* miss xfr - ni W1C abt */
#define MBASR_MBEXC 0x00000080 /* except - ni W1C abt */
#define MBASR_MBDPE 0x00000040 /* dat perr - ni W1C abt */
#define MBASR_MAPPE 0x00000020 /* map perr - ni W1C abt */
#define MBASR_INVM 0x00000010 /* inv map - W1C abt */
#define MBASR_ERCONF 0x00000008 /* err conf - ni W1C abt */
#define MBASR_RDS 0x00000004 /* RDS - ni W1C abt */
#define MBASR_ITMO 0x00000002 /* timeout - W1C abt */
#define MBASR_RTMO 0x00000001 /* rd timeout - W1C abt */
#define MBASR_RD 0xE08F7FFF
#define MBASR_W1C 0x608F7FFF
#define MBASR_ABORTS 0x00000FFF
#define MBASR_INTR 0x000F7000
/* Virtual address register */
#define MBAVA_OF 0x3
#define MBAVA_RD 0x0001FFFF
#define MBAVA_WR (MBAVA_RD)
/* Byte count */
#define MBABC_OF 0x4
#define MBABC_RD 0xFFFFFFFF
#define MBABC_WR 0x0000FFFF
#define MBABC_V_CNT 16 /* active count */
/* Diagnostic register */
#define MBADR_OF 0x5
#define MBADR_RD 0xFFFFFFFF
#define MBADR_WR 0xFFC00000
/* Selected map entry - read only */
#define MBASMR_OF 0x6
#define MBASMR_RD (MBAMAP_RD)
/* Command register (SBI) - read only */
#define MBACMD_OF 0x7
/* External registers */
#define MBA_CS1 0x00 /* device CSR1 */
#define MBA_CS1_WR 0x3F /* writeable bits */
#define MBA_CS1_DT 0x28 /* >= for data xfr */
/* Map registers */
#define MBAMAP_VLD 0x80000000 /* valid */
#define MBAMAP_PAG 0x001FFFFF
#define MBAMAP_RD (MBAMAP_VLD | MBAMAP_PAG)
#define MBAMAP_WR (MBAMAP_RD)
struct mbctx {
uint32 cnf; /* config reg */
uint32 cr; /* control reg */
uint32 sr; /* status reg */
uint32 va; /* virt addr */
uint32 bc; /* byte count */
uint32 dr; /* diag reg */
uint32 smr; /* sel map reg */
uint32 map[MBA_NMAPR]; /* map */
};
typedef struct mbctx MBACTX;
MBACTX massbus[MBA_NUM];
extern uint32 nexus_req[NEXUS_HLVL];
extern UNIT cpu_unit;
extern FILE *sim_log;
extern int32 sim_switches;
t_stat mba_reset (DEVICE *dptr);
t_stat mba_rdreg (int32 *val, int32 pa, int32 mode);
t_stat mba_wrreg (int32 val, int32 pa, int32 lnt);
t_bool mba_map_addr (uint32 va, uint32 *ma, uint32 mb);
void mba_set_int (uint32 mb);
void mba_clr_int (uint32 mb);
void mba_upd_sr (uint32 set, uint32 clr, uint32 mb);
DEVICE mba0_dev, mba1_dev;
DIB mba0_dib, mba1_dib;
extern int32 ReadB (uint32 pa);
extern int32 ReadW (uint32 pa);
extern int32 ReadL (uint32 pa);
extern void WriteB (uint32 pa, int32 val);
extern void WriteW (uint32 pa, int32 val);
extern void WriteL (uint32 pa, int32 val);
/* Maps */
static MBACTX *ctxmap[MBA_NUM] = { &massbus[0], &massbus[1] };
static DEVICE *devmap[MBA_NUM] = { &mba0_dev, &mba1_dev };
/* Massbus register dispatches */
static t_stat (*mbregR[MBA_NUM])(int32 *dat, int32 ad, int32 md);
static t_stat (*mbregW[MBA_NUM])(int32 dat, int32 ad, int32 md);
static int32 (*mbabort[MBA_NUM])(void);
/* Massbus adapter data structures
mba_dev UBA device descriptor
mba_unit UBA units
mba_reg UBA register list
*/
DIB mba0_dib = { TR_MBA0, 0, &mba_rdreg, &mba_wrreg, 0, NVCL (MBA0) };
UNIT mba0_unit = { UDATA (NULL, 0, 0) };
REG mba0_reg[] = {
{ HRDATA (CNFR, massbus[0].cnf, 32) },
{ HRDATA (CR, massbus[0].cr, 4) },
{ HRDATA (SR, massbus[0].sr, 32) },
{ HRDATA (VA, massbus[0].va, 17) },
{ HRDATA (BC, massbus[0].bc, 32) },
{ HRDATA (DR, massbus[0].dr, 32) },
{ HRDATA (SMR, massbus[0].dr, 32) },
{ BRDATA (MAP, massbus[0].map, 16, 32, MBA_NMAPR) },
{ FLDATA (NEXINT, nexus_req[IPL_MBA0], TR_MBA0) },
{ NULL } };
MTAB mba0_mod[] = {
{ MTAB_XTD|MTAB_VDV, TR_MBA0, "NEXUS", NULL,
NULL, &show_nexus },
{ 0 } };
DEVICE mba0_dev = {
"MBA0", &mba0_unit, mba0_reg, mba0_mod,
1, 0, 0, 0, 0, 0,
NULL, NULL, &mba_reset,
NULL, NULL, NULL,
&mba0_dib, DEV_NEXUS };
DIB mba1_dib = { TR_MBA1, 0, &mba_rdreg, &mba_wrreg, 0, NVCL (MBA0) };
UNIT mba1_unit = { UDATA (NULL, 0, 0) };
MTAB mba1_mod[] = {
{ MTAB_XTD|MTAB_VDV, TR_MBA1, "NEXUS", NULL,
NULL, &show_nexus },
{ 0 } };
REG mba1_reg[] = {
{ HRDATA (CNFR, massbus[1].cnf, 32) },
{ HRDATA (CR, massbus[1].cr, 4) },
{ HRDATA (SR, massbus[1].sr, 32) },
{ HRDATA (VA, massbus[1].va, 17) },
{ HRDATA (BC, massbus[1].bc, 32) },
{ HRDATA (DR, massbus[1].dr, 32) },
{ HRDATA (SMR, massbus[1].dr, 32) },
{ BRDATA (MAP, massbus[1].map, 16, 32, MBA_NMAPR) },
{ FLDATA (NEXINT, nexus_req[IPL_MBA1], TR_MBA1) },
{ NULL } };
DEVICE mba1_dev = {
"MBA1", &mba1_unit, mba1_reg, mba1_mod,
1, 0, 0, 0, 0, 0,
NULL, NULL, &mba_reset,
NULL, NULL, NULL,
&mba1_dib, DEV_NEXUS };
/* Read Massbus adapter register */
t_stat mba_rdreg (int32 *val, int32 pa, int32 mode)
{
int32 mb, ofs, drv, rtype;
t_stat r;
MBACTX *mbp;
mb = NEXUS_GETNEX (pa) - TR_MBA0; /* get MBA */
if (mb >= MBA_NUM) return SCPE_NXM; /* valid? */
mbp = ctxmap[mb]; /* get context */
rtype = MBA_RTYPE (pa); /* get reg type */
switch (rtype) { /* case on type */
case MBART_INT: /* internal */
ofs = MBA_INTOFS (pa); /* check range */
switch (ofs) {
case MBACNF_OF: /* CNF */
*val = (mbp->cnf & MBACNF_RD) | MBACNF_CODE;
break;
case MBACR_OF: /* CR */
*val = mbp->cr & MBACR_RD;
break;
case MBASR_OF: /* SR */
*val = mbp->sr & MBASR_RD;
break;
case MBAVA_OF: /* VA */
*val = mbp->va & MBAVA_RD;
break;
case MBABC_OF: /* BC */
*val = mbp->bc & MBABC_RD;
break;
case MBADR_OF: /* DR */
*val = mbp->dr & MBADR_RD;
break;
case MBASMR_OF: /* SMR */
*val = mbp->smr & MBASMR_RD;
break;
case MBACMD_OF: /* CMD */
*val = 0;
break;
default:
return SCPE_NXM;
}
break;
case MBART_EXT: /* external */
if (!mbregR[mb]) return SCPE_NXM; /* device there? */
drv = MBA_EXTDRV (pa); /* get dev num */
ofs = MBA_EXTOFS (pa); /* get reg offs */
r = mbregR[mb] (val, ofs, drv); /* call device */
if (r == MBE_NXD) mba_upd_sr (MBASR_NFD, 0, mb);/* nx drive? */
else if (r == MBE_NXR) return SCPE_NXM; /* nx reg? */
break;
case MBART_MAP: /* map */
ofs = MBA_INTOFS (pa);
*val = mbp->map[ofs] & MBAMAP_RD;
break;
default:
return SCPE_NXM; }
return SCPE_OK;
}
/* Write Massbus adapter register */
t_stat mba_wrreg (int32 val, int32 pa, int32 lnt)
{
int32 mb, ofs, drv, rtype;
t_stat r;
t_bool cs1dt;
MBACTX *mbp;
mb = NEXUS_GETNEX (pa) - TR_MBA0; /* get MBA */
if (mb >= MBA_NUM) return SCPE_NXM; /* valid? */
mbp = ctxmap[mb]; /* get context */
rtype = MBA_RTYPE (pa); /* get reg type */
switch (rtype) { /* case on type */
case MBART_INT: /* internal */
ofs = MBA_INTOFS (pa); /* check range */
switch (ofs) {
case MBACNF_OF: /* CNF */
mbp->cnf = mbp->cnf & ~(val & MBACNF_W1C);
break;
case MBACR_OF: /* CR */
if (val & MBACR_INIT) /* init? */
mba_reset (devmap[mb]); /* reset MBA */
if ((val & MBACR_ABORT) && (mbp->sr & MBASR_DTBUSY)) {
if (mbabort[mb]) mbabort[mb] (); /* abort? */
mba_upd_sr (MBASR_DTABT, 0, mb); }
if ((val & MBACR_MNT) && (mbp->sr & MBASR_DTBUSY)) {
mba_upd_sr (MBASR_PGE, 0, mb); /* mnt & xfer? */
val = val & ~MBACR_MNT; }
if ((val & MBACR_IE) == 0) mba_clr_int (mb);
mbp->cr = (mbp->cr & ~MBACR_WR) | (val & MBACR_WR);
break;
case MBASR_OF: /* SR */
mbp->sr = mbp->sr & ~(val & MBASR_W1C);
break;
case MBAVA_OF: /* VA */
if (mbp->sr & MBASR_DTBUSY) /* err if xfr */
mba_upd_sr (MBASR_PGE, 0, mb);
else mbp->va = val & MBAVA_WR;
break;
case MBABC_OF: /* BC */
if (mbp->sr & MBASR_DTBUSY) /* err if xfr */
mba_upd_sr (MBASR_PGE, 0, mb);
else {
val = val & MBABC_WR;
mbp->bc = (val << MBABC_V_CNT) | val;
}
break;
case MBADR_OF: /* DR */
mbp->dr = (mbp->dr & ~MBADR_WR) | (val & MBADR_WR);
break;
default:
return SCPE_NXM;
}
break;
case MBART_EXT: /* external */
if (!mbregW[mb]) return SCPE_NXM; /* device there? */
drv = MBA_EXTDRV (pa); /* get dev num */
ofs = MBA_EXTOFS (pa); /* get reg offs */
cs1dt = (ofs == MBA_CS1) && (val & CSR_GO) && /* starting xfr? */
((val & MBA_CS1_WR) >= MBA_CS1_DT);
if (cs1dt && (mbp->sr & MBASR_DTBUSY)) { /* xfr while busy? */
mba_upd_sr (MBASR_PGE, 0, mb); /* prog error */
break;
}
r = mbregW[mb] (val, ofs, drv); /* write dev reg */
if (r == MBE_NXD) mba_upd_sr (MBASR_NFD, 0, mb);/* nx drive? */
else if (r == MBE_NXR) return SCPE_NXM; /* nx reg? */
if (cs1dt && (r == SCPE_OK)) /* did dt start? */
mbp->sr = (mbp->sr | MBASR_DTBUSY) & ~MBASR_W1C;
break;
case MBART_MAP: /* map */
ofs = MBA_INTOFS (pa);
mbp->map[ofs] = val & MBAMAP_WR;
break;
default:
return SCPE_NXM; }
return SCPE_OK;
}
/* Massbus I/O routine
mb_rdbufW - fetch word buffer from memory
mb_wrbufW - store word buffer into memory
mb_chbufW - compare word buffer with memory
Returns number of bytes successfully transferred/checked
*/
int32 mba_rdbufW (uint32 mb, int32 bc, uint16 *buf)
{
MBACTX *mbp;
int32 i, j, ba, mbc, pbc;
uint32 pa, dat;
if (mb >= MBA_NUM) return 0; /* valid MBA? */
mbp = ctxmap[mb]; /* get context */
ba = mbp->va; /* get virt addr */
mbc = ((MBABC_WR + 1) - (mbp->bc >> MBABC_V_CNT)) & MBABC_WR; /* get Mbus bc */
if (bc > mbc) bc = mbc; /* use smaller */
for (i = 0; i < bc; i = i + pbc) { /* loop by pages */
if (!mba_map_addr (ba + i, &pa, mb)) break; /* page inv? */
if (!ADDR_IS_MEM (pa)) { /* NXM? */
mba_upd_sr (MBASR_RTMO, 0, mb);
break; }
pbc = VA_PAGSIZE - VA_GETOFF (pa); /* left in page */
if (pbc > (bc - i)) pbc = bc - i; /* limit to rem xfr */
if ((pa | pbc) & 1) { /* aligned word? */
for (j = 0; j < pbc; pa++, j++) { /* no, bytes */
if ((i + j) & 1) { /* odd byte? */
*buf = (*buf & BMASK) | (ReadB (pa) << 8);
buf++;
}
else *buf = (*buf & ~BMASK) | ReadB (pa);
}
}
else if ((pa | pbc) & 3) { /* aligned LW? */
for (j = 0; j < pbc; pa = pa + 2, j = j + 2) { /* no, words */
*buf++ = ReadW (pa); /* get word */
}
}
else { /* yes, do by LW */
for (j = 0; j < pbc; pa = pa + 4, j = j + 4) {
dat = ReadL (pa); /* get lw */
*buf++ = dat & WMASK; /* low 16b */
*buf++ = (dat >> 16) & WMASK; /* high 16b */
}
}
}
return i;
}
int32 mba_wrbufW (uint32 mb, int32 bc, uint16 *buf)
{
MBACTX *mbp;
int32 i, j, ba, mbc, pbc;
uint32 pa, dat;
if (mb >= MBA_NUM) return 0; /* valid MBA? */
mbp = ctxmap[mb]; /* get context */
ba = mbp->va; /* get virt addr */
mbc = ((MBABC_WR + 1) - (mbp->bc >> MBABC_V_CNT)) & MBABC_WR; /* get Mbus bc */
if (bc > mbc) bc = mbc; /* use smaller */
for (i = 0; i < bc; i = i + pbc) { /* loop by pages */
if (!mba_map_addr (ba + i, &pa, mb)) break; /* page inv? */
if (!ADDR_IS_MEM (pa)) { /* NXM? */
mba_upd_sr (MBASR_RTMO, 0, mb);
break; }
pbc = VA_PAGSIZE - VA_GETOFF (pa); /* left in page */
if (pbc > (bc - i)) pbc = bc - i; /* limit to rem xfr */
if ((pa | pbc) & 1) { /* aligned word? */
for (j = 0; j < pbc; pa++, j++) { /* no, bytes */
if ((i + j) & 1) {
WriteB (pa, (*buf >> 8) & BMASK);
buf++; }
else WriteB (pa, *buf & BMASK);
}
}
else if ((pa | pbc) & 3) { /* aligned LW? */
for (j = 0; j < pbc; pa = pa + 2, j = j + 2) { /* no, words */
WriteW (pa, *buf); /* write word */
buf++;
}
}
else { /* yes, do by LW */
for (j = 0; j < pbc; pa = pa + 4, j = j + 4) {
dat = (uint32) *buf++; /* get low 16b */
dat = dat | (((uint32) *buf++) << 16); /* merge hi 16b */
WriteL (pa, dat); /* store LW */
}
}
}
return i;
}
int32 mba_chbufW (uint32 mb, int32 bc, uint16 *buf)
{
MBACTX *mbp;
int32 i, j, ba, mbc, pbc;
uint32 pa, dat, cmp;
if (mb >= MBA_NUM) return 0; /* valid MBA? */
mbp = ctxmap[mb]; /* get context */
ba = mbp->va; /* get virt addr */
mbc = ((MBABC_WR + 1) - (mbp->bc >> MBABC_V_CNT)) & MBABC_WR; /* get Mbus bc */
if (bc > mbc) bc = mbc; /* use smaller */
for (i = 0; i < bc; i = i + pbc) { /* loop by pages */
if (!mba_map_addr (ba + i, &pa, mb)) break; /* page inv? */
if (!ADDR_IS_MEM (pa)) { /* NXM? */
mba_upd_sr (MBASR_RTMO, 0, mb);
break; }
pbc = VA_PAGSIZE - VA_GETOFF (pa); /* left in page */
if (pbc > (bc - i)) pbc = bc - i; /* limit to rem xfr */
for (j = 0; j < pbc; j++, pa++) { /* byte by byte */
cmp = ReadB (pa);
if ((i + j) & 1) dat = (*buf++ >> 8) & BMASK;
else dat = *buf & BMASK;
if (cmp != dat) {
mba_upd_sr ((j & 1)? MBASR_WCEU: MBASR_WCEL, 0, mb);
break;
} /* end if */
} /* end for j */
} /* end for i */
return i;
}
/* Map an address via the translation map */
t_bool mba_map_addr (uint32 va, uint32 *ma, uint32 mb)
{
MBACTX *mbp = ctxmap[mb];
uint32 vblk = (va >> VA_V_VPN); /* map index */
uint32 mmap = mbp->map[vblk]; /* get map */
mbp->smr = mmap; /* save map reg */
if (mmap & MBAMAP_VLD) { /* valid? */
*ma = ((mmap & MBAMAP_PAG) << VA_V_VPN) + VA_GETOFF (va);
return 1; } /* legit addr */
mba_upd_sr (MBASR_INVM, 0, mb); /* invalid map */
return 0;
}
/* Device access, status, and interrupt routines */
void mba_set_don (uint32 mb)
{
mba_upd_sr (MBASR_DTCMP, 0, mb);
return;
}
void mba_upd_ata (uint32 mb, uint32 val)
{
if (val) mba_upd_sr (MBASR_ATA, 0, mb);
else mba_upd_sr (0, MBASR_ATA, mb);
return;
}
void mba_set_exc (uint32 mb)
{
mba_upd_sr (MBASR_MBEXC, 0, mb);
return;
}
int32 mba_get_bc (uint32 mb)
{
MBACTX *mbp;
if (mb >= MBA_NUM) return 0;
mbp = ctxmap[mb];
return (((MBABC_WR + 1) - (mbp->bc >> MBABC_V_CNT)) & MBABC_WR);
}
void mba_set_int (uint32 mb)
{
DEVICE *dptr;
DIB *dibp;
if (mb >= MBA_NUM) return;
dptr = devmap[mb];
dibp = (DIB *) dptr->ctxt;
nexus_req[dibp->vloc >> 5] |= (1u << (dibp->vloc & 0x1F));
return;
}
void mba_clr_int (uint32 mb)
{
DEVICE *dptr;
DIB *dibp;
if (mb >= MBA_NUM) return;
dptr = devmap[mb];
dibp = (DIB *) dptr->ctxt;
nexus_req[dibp->vloc >> 5] &= ~(1u << (dibp->vloc & 0x1F));
return;
}
void mba_upd_sr (uint32 set, uint32 clr, uint32 mb)
{
MBACTX *mbp;
if (mb >= MBA_NUM) return;
mbp = ctxmap[mb];
if (set & MBASR_ABORTS) set |= (MBASR_DTCMP|MBASR_DTABT);
if (set & (MBASR_DTCMP|MBASR_DTABT)) mbp->sr &= ~MBASR_DTBUSY;
mbp->sr = (mbp->sr | set) & ~clr;
if ((set & MBASR_INTR) && (mbp->cr & MBACR_IE))
mba_set_int (mb);
return;
}
/* Reset Massbus adapter */
t_stat mba_reset (DEVICE *dptr)
{
int32 i, mb;
DIB *dibp;
MBACTX *mbp;
dibp = (DIB *) dptr->ctxt;
if (dibp == NULL) return SCPE_IERR;
mb = dibp->ba - TR_MBA0;
if ((mb < 0) || (mb >= MBA_NUM)) return SCPE_IERR;
mbp = ctxmap[mb];
mbp->cnf = 0;
mbp->cr = mbp->cr & MBACR_MNT;
mbp->sr = 0;
mbp->bc = 0;
mbp->va = 0;
mbp->dr = 0;
mbp->smr = 0;
if (sim_switches & SWMASK ('P')) {
for (i = 0; i < MBA_NMAPR; i++) mbp->map[i] = 0;
}
if (mbabort[mb]) mbabort[mb] (); /* reset device */
return SCPE_OK;
}
/* Show Massbus adapter number */
t_stat mba_show_num (FILE *st, UNIT *uptr, int32 val, void *desc)
{
DEVICE *dptr = find_dev_from_unit (uptr);
DIB *dibp;
if (dptr == NULL) return SCPE_IERR;
dibp = (DIB *) dptr->ctxt;
if (dibp == NULL) return SCPE_IERR;
fprintf (st, "Massbus adapter %d", dibp->ba);
return SCPE_OK;
}
/* Init Mbus tables */
void init_mbus_tab (void)
{
uint32 i;
for (i = 0; i < MBA_NUM; i++) {
mbregR[i] = NULL;
mbregW[i] = NULL;
mbabort[i] = NULL;
}
return;
}
/* Build dispatch tables */
t_stat build_mbus_tab (DEVICE *dptr, DIB *dibp)
{
uint32 idx;
if ((dptr == NULL) || (dibp == NULL)) return SCPE_IERR; /* validate args */
idx = dibp->ba; /* Mbus # */
if (idx >= MBA_NUM) return SCPE_STOP;
if ((mbregR[idx] && dibp->rd && /* conflict? */
(mbregR[idx] != dibp->rd)) ||
(mbregW[idx] && dibp->wr &&
(mbregW[idx] != dibp->wr)) ||
(mbabort[idx] && dibp->ack[0] &&
(mbabort[idx] != dibp->ack[0]))) {
printf ("Massbus %s assignment conflict at %d\n",
sim_dname (dptr), dibp->ba);
if (sim_log) fprintf (sim_log,
"Massbus %s assignment conflict at %d\n",
sim_dname (dptr), dibp->ba);
return SCPE_STOP;
}
if (dibp->rd) mbregR[idx] = dibp->rd; /* set rd dispatch */
if (dibp->wr) mbregW[idx] = dibp->wr; /* set wr dispatch */
if (dibp->ack[0]) mbabort[idx] = dibp->ack[0]; /* set abort dispatch */
return SCPE_OK;
}

View file

@ -1,901 +0,0 @@
/* vax780_sbimem.c: VAX 11/780 SBI and memory controller
Copyright (c) 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 module contains the VAX 11/780 system-specific registers and devices.
mctl0, mctl1 MS780C/E memory controllers
sbi bus controller
*/
#include "vax_defs.h"
/* 11/780 specific IPRs */
/* Writeable control store */
#define WCSA_RW 0xFFFF /* writeable */
#define WCSA_ADDR 0x1FFF /* addr */
#define WCSA_CTR 0x6000 /* counter */
#define WCSA_CTR_INC 0x2000 /* increment */
#define WCSA_CTR_MAX 0x6000 /* max value */
#define WCSD_RD_VAL 0xFF /* fixed read val */
#define WCSD_WR 0xFFFFFFFF /* write */
#define MBRK_RW 0x1FFF /* microbreak */
/* System registers */
#define SBIFS_RD (0x031F0000|SBI_FAULTS) /* SBI faults */
#define SBIFS_WR 0x03140000
#define SBIFS_W1C 0x00080000
#define SBISC_RD 0xFFFF0000 /* SBI silo comp */
#define SBISC_WR 0x7FFF0000
#define SBISC_LOCK 0x80000000 /* lock */
#define SBIMT_RD 0xFFFFFF00 /* SBI maint */
#define SBIMT_WR 0xFFFFF900
#define SBIER_CRDIE 0x00008000 /* SBI error, CRD IE */
#define SBIER_CRD 0x00004000 /* CRD */
#define SBIER_RDS 0x00002000 /* RDS */
#define SBIER_TMO 0x00001000 /* timeout */
#define SBIER_STA 0x00000C00 /* timeout status (0) */
#define SBIER_CNF 0x00000100 /* error confirm */
#define SBIER_IBRDS 0x00000080
#define SBIER_IBTMO 0x00000040
#define SBIER_IBSTA 0x00000030
#define SBIER_IBCNF 0x00000008
#define SBIER_MULT 0x00000004 /* multiple errors */
#define SBIER_FREE 0x00000002 /* SBI free */
#define SBIER_RD 0x0000FDFE
#define SBIER_WR 0x00008000
#define SBIER_W1C 0x000070C0
#define SBIER_TMOW1C (SBIER_TMO|SBIER_STA|SBIER_CNF|SBIER_MULT)
#define SBIER_IBTW1C (SBIER_IBTMO|SBIER_STA|SBIER_IBCNF)
#define SBITMO_V_MODE 30 /* mode */
#define SBITMO_VIRT 0x20000000 /* physical */
/* Memory controller register A */
#define MCRA_OF 0x0
#define MCRA_SUMM 0x00100000 /* err summ (MS780E) */
#define MCRA_C_SIZE 0x00007C00 /* array size - fixed */
#define MCRA_V_SIZE 9
#define MCRA_ILVE 0x00000100 /* interleave wr enab */
#define MCRA_TYPE 0x000000F8 /* type */
#define MCRA_C_TYPE 0x00000010 /* 16k uninterleaved */
#define MCRA_E_TYPE 0x0000006A /* 256k upper + lower */
#define MCRA_ILV 0x00000007 /* interleave */
#define MCRA_RD (0x00107FFF|SBI_FAULTS)
#define MCRA_WR 0x00000100
/* Memory controller register B */
#define MCRB_OF 0x1
#define MCRB_FP 0xF0000000 /* file pointers */
#define MCRB_V_SA 15 /* start addr */
#define MCRB_M_SA 0x1FFF
#define MCRB_SA (MCRB_M_SA << MCRB_V_SA)
#define MCRB_SAE 0x00004000 /* start addr wr enab */
#define MCRB_INIT 0x00003000 /* init state */
#define MCRB_REF 0x00000400 /* refresh */
#define MCRB_ECC 0x000003FF /* ECC for diags */
#define MCRB_RD 0xFFFFF7FF
#define MCRB_WR 0x000043FF
/* Memory controller register C,D */
#define MCRC_OF 0x2
#define MCRD_OF 0x3
#define MCRC_DCRD 0x40000000 /* disable CRD */
#define MCRC_HER 0x20000000 /* high error rate */
#define MCRC_ERL 0x10000000 /* log error */
#define MCRC_C_ER 0x0FFFFFFF /* MS780C error */
#define MCRC_E_PE1 0x00080000 /* MS780E par ctl 1 */
#define MCRC_E_PE0 0x00040000 /* MS780E par ctl 0 */
#define MCRC_E_CRD 0x00000200 /* MS780E CRD */
#define MCRC_E_PEW 0x00000100 /* MS780E par err wr */
#define MCRC_E_USEQ 0x00000080 /* MS780E seq err */
#define MCRC_C_RD 0x7FFFFFFF
#define MCRC_E_RD 0x700C0380
#define MCRC_WR 0x40000000
#define MCRC_C_W1C 0x30000000
#define MCRC_E_W1C 0x300C0380
#define MCRMAX_OF 0x4
#define MCRROM_OF 0x400
/* VAX-11/780 boot device definitions */
struct boot_dev {
char *name;
int32 code;
int32 let;
};
uint32 wcs_addr = 0;
uint32 wcs_data = 0;
uint32 wcs_mbrk = 0;
uint32 nexus_req[NEXUS_HLVL]; /* nexus int req */
uint32 sbi_fs = 0; /* SBI fault status */
uint32 sbi_sc = 0; /* SBI silo comparator */
uint32 sbi_mt = 0; /* SBI maintenance */
uint32 sbi_er = 0; /* SBI error status */
uint32 sbi_tmo = 0; /* SBI timeout addr */
uint32 mcr_a[MCTL_NUM];
uint32 mcr_b[MCTL_NUM];
uint32 mcr_c[MCTL_NUM];
uint32 mcr_d[MCTL_NUM];
uint32 rom_lw[MCTL_NUM][ROMSIZE >> 2];
static t_stat (*nexusR[NEXUS_NUM])(int32 *dat, int32 ad, int32 md);
static t_stat (*nexusW[NEXUS_NUM])(int32 dat, int32 ad, int32 md);
static struct boot_dev boot_tab[] = {
{ "RP", BOOT_MB, 0 },
{ "HK", BOOT_HK, 0 },
{ "RL", BOOT_RL, 0 },
{ "RQ", BOOT_UDA, 'A' << 24 },
{ "TQ", BOOT_TK, 'A' << 24 },
{ NULL } };
extern int32 R[16];
extern int32 PSL;
extern int32 ASTLVL, SISR;
extern int32 mapen, pme, trpirq;
extern int32 in_ie;
extern int32 mchk_va, mchk_ref;
extern int32 cpu_extmem;
extern int32 crd_err, mem_err, hlt_pin;
extern int32 tmr_int, tti_int, tto_int;
extern jmp_buf save_env;
extern int32 p1;
extern int32 sim_switches;
extern UNIT cpu_unit;
extern DEVICE *sim_devices[];
extern FILE *sim_log;
extern CTAB *sim_vm_cmd;
t_stat sbi_reset (DEVICE *dptr);
t_stat mctl_reset (DEVICE *dptr);
t_stat mctl_rdreg (int32 *val, int32 pa, int32 mode);
t_stat mctl_wrreg (int32 val, int32 pa, int32 mode);
void sbi_set_tmo (int32 pa);
t_stat vax780_boot (int32 flag, char *ptr);
void uba_eval_int (void);
extern void Write (uint32 va, int32 val, int32 lnt, int32 acc);
extern int32 intexc (int32 vec, int32 cc, int32 ipl, int ei);
extern int32 iccs_rd (void);
extern int32 nicr_rd (void);
extern int32 icr_rd (void);
extern int32 todr_rd (void);
extern int32 rxcs_rd (void);
extern int32 rxdb_rd (void);
extern int32 txcs_rd (void);
extern void iccs_wr (int32 dat);
extern void nicr_wr (int32 dat);
extern void todr_wr (int32 dat);
extern void rxcs_wr (int32 dat);
extern void txcs_wr (int32 dat);
extern void txdb_wr (int32 dat);
extern void init_mbus_tab (void);
extern void init_ubus_tab (void);
extern t_stat build_mbus_tab (DEVICE *dptr, DIB *dibp);
extern t_stat build_ubus_tab (DEVICE *dptr, DIB *dibp);
/* SBI data structures
sbi_dev SBI device descriptor
sbi_unit SBI unit
sbi_reg SBI register list
*/
UNIT sbi_unit = { UDATA (NULL, 0, 0) };
REG sbi_reg[] = {
{ HRDATA (NREQ14, nexus_req[0], 16) },
{ HRDATA (NREQ15, nexus_req[1], 16) },
{ HRDATA (NREQ16, nexus_req[2], 16) },
{ HRDATA (NREQ17, nexus_req[3], 16) },
{ HRDATA (WCSA, wcs_addr, 16) },
{ HRDATA (WCSD, wcs_data, 32) },
{ HRDATA (MBRK, wcs_mbrk, 13) },
{ HRDATA (SBIFS, sbi_fs, 32) },
{ HRDATA (SBISC, sbi_sc, 32) },
{ HRDATA (SBIMT, sbi_mt, 32) },
{ HRDATA (SBIER, sbi_er, 32) },
{ HRDATA (SBITMO, sbi_tmo, 32) },
{ NULL } };
DEVICE sbi_dev = {
"SBI", &sbi_unit, sbi_reg, NULL,
1, 16, 16, 1, 16, 8,
NULL, NULL, &sbi_reset,
NULL, NULL, NULL,
NULL, 0 };
/* MCTLx data structures
mctlx_dev MCTLx device descriptor
mctlx_unit MCTLx unit
mctlx_reg MCTLx register list
*/
DIB mctl0_dib[] = { TR_MCTL0, 0, &mctl_rdreg, &mctl_wrreg, 0 };
UNIT mctl0_unit = { UDATA (NULL, 0, 0) };
REG mctl0_reg[] = {
{ HRDATA (CRA, mcr_a[0], 32) },
{ HRDATA (CRB, mcr_b[0], 32) },
{ HRDATA (CRC, mcr_c[0], 32) },
{ HRDATA (CRD, mcr_d[0], 32) },
{ BRDATA (ROM, rom_lw[0], 16, 32, ROMSIZE >> 2) },
{ NULL } };
MTAB mctl0_mod[] = {
{ MTAB_XTD|MTAB_VDV, TR_MCTL0, "NEXUS", NULL,
NULL, &show_nexus },
{ 0 } };
DEVICE mctl0_dev = {
"MCTL0", &mctl0_unit, mctl0_reg, mctl0_mod,
1, 16, 16, 1, 16, 8,
NULL, NULL, &mctl_reset,
NULL, NULL, NULL,
&mctl0_dib, DEV_NEXUS };
DIB mctl1_dib[] = { TR_MCTL1, 0, &mctl_rdreg, &mctl_wrreg, 0 };
UNIT mctl1_unit = { UDATA (NULL, 0, 0) };
MTAB mctl1_mod[] = {
{ MTAB_XTD|MTAB_VDV, TR_MCTL1, "NEXUS", NULL,
NULL, &show_nexus },
{ 0 } };
REG mctl1_reg[] = {
{ HRDATA (CRA, mcr_a[1], 32) },
{ HRDATA (CRB, mcr_b[1], 32) },
{ HRDATA (CRC, mcr_c[1], 32) },
{ HRDATA (CRD, mcr_d[1], 32) },
{ BRDATA (ROM, rom_lw[1], 16, 32, ROMSIZE >> 2) },
{ NULL } };
DEVICE mctl1_dev = {
"MCTL1", &mctl1_unit, mctl1_reg, mctl1_mod,
1, 16, 16, 1, 16, 8,
NULL, NULL, &mctl_reset,
NULL, NULL, NULL,
&mctl1_dib, DEV_NEXUS };
DIB mctl_dib[] = { TR_MCTL0, 2, &mctl_rdreg, &mctl_wrreg, 0 };
/* Special boot command, overrides regular boot */
CTAB vax780_cmd[] = {
{ "BOOT", &vax780_boot, RU_BOOT,
"bo{ot} <device>{/R5:flg} boot device\n" },
{ NULL } };
/* The VAX 11/780 has three sources of interrupts
- internal device interrupts (CPU, console, clock)
- nexus interupts (e.g., memory controller, MBA, UBA)
- external device interrupts (Unibus)
Internal devices vector to fixed SCB locations.
Nexus interrupts vector to an SCB location based on this
formula: SCB_NEXUS + ((IPL - 0x14) * 0x40) + (TR# * 0x4)
External device interrupts do not vector directly.
Instead, the interrupt handler for a given UBA IPL
reads a vector register that contains the Unibus vector
for that IPL.
/* Find highest priority vectorable interrupt */
int32 eval_int (void)
{
int32 ipl = PSL_GETIPL (PSL);
int32 i, t;
static const int32 sw_int_mask[IPL_SMAX] = {
0xFFFE, 0xFFFC, 0xFFF8, 0xFFF0, /* 0 - 3 */
0xFFE0, 0xFFC0, 0xFF80, 0xFF00, /* 4 - 7 */
0xFE00, 0xFC00, 0xF800, 0xF000, /* 8 - B */
0xE000, 0xC000, 0x8000 }; /* C - E */
if (hlt_pin) return IPL_HLTPIN; /* hlt pin int */
if ((ipl < IPL_MEMERR) && mem_err) return IPL_MEMERR; /* mem err int */
if ((ipl < IPL_CRDERR) && crd_err) return IPL_CRDERR; /* crd err int */
if ((ipl < IPL_CLKINT) && tmr_int) return IPL_CLKINT; /* clock int */
uba_eval_int (); /* update UBA */
for (i = IPL_HMAX; i >= IPL_HMIN; i--) { /* chk hwre int */
if (i <= ipl) return 0; /* at ipl? no int */
if (nexus_req[i - IPL_HMIN]) return i; } /* req != 0? int */
if ((ipl < IPL_TTINT) && (tti_int || tto_int)) /* console int */
return IPL_TTINT;
if (ipl >= IPL_SMAX) return 0; /* ipl >= sw max? */
if ((t = SISR & sw_int_mask[ipl]) == 0) return 0; /* eligible req */
for (i = IPL_SMAX; i > ipl; i--) { /* check swre int */
if ((t >> i) & 1) return i; } /* req != 0? int */
return 0;
}
/* Return vector for highest priority hardware interrupt at IPL lvl */
int32 get_vector (int32 lvl)
{
int32 i;
int32 l = lvl - IPL_HMIN;
if (lvl == IPL_MEMERR) { /* mem error? */
mem_err = 0;
return SCB_MEMERR; }
if (lvl == IPL_CRDERR) { /* CRD error? */
crd_err = 0;
return SCB_CRDERR; }
if ((lvl == IPL_CLKINT) && tmr_int) { /* clock? */
tmr_int = 0; /* clear req */
return SCB_INTTIM; } /* return vector */
if (lvl > IPL_HMAX) { /* error req lvl? */
ABORT (STOP_UIPL); } /* unknown intr */
if ((lvl <= IPL_HMAX) && (lvl >= IPL_HMIN)) { /* nexus? */
for (i = 0; nexus_req[l] && (i < NEXUS_NUM); i++) {
if ((nexus_req[l] >> i) & 1) {
nexus_req[l] = nexus_req[l] & ~(1u << i);
return SCB_NEXUS + (l << 6) + (i << 2); /* return vector */
}
}
}
if (lvl == IPL_TTINT) { /* console? */
if (tti_int) { /* input? */
tti_int = 0; /* clear req */
return SCB_TTI; } /* return vector */
if (tto_int) { /* output? */
tto_int = 0; /* clear req */
return SCB_TTO; } /* return vector */
}
return 0;
}
/* Read 780-specific IPR's */
int32 ReadIPR (int32 rg)
{
int32 val;
switch (rg) {
case MT_ICCS: /* ICCS */
val = iccs_rd ();
break;
case MT_NICR: /* NICR */
val = nicr_rd ();
break;
case MT_ICR: /* ICR */
val = icr_rd ();
break;
case MT_TODR: /* TODR */
val = todr_rd ();
break;
case MT_ACCS: /* ACCS (not impl) */
val = 0;
break;
case MT_WCSA: /* WCSA */
val = wcs_addr & WCSA_RW;
break;
case MT_WCSD: /* WCSD */
val = WCSD_RD_VAL;
break;
case MT_RXCS: /* RXCS */
val = rxcs_rd ();
break;
case MT_RXDB: /* RXDB */
val = rxdb_rd ();
break;
case MT_TXCS: /* TXCS */
val = txcs_rd ();
break;
case MT_TXDB: /* TXDB */
val = 0;
break;
case MT_SBIFS: /* SBIFS */
val = sbi_fs & SBIFS_RD;
break;
case MT_SBIS: /* SBIS */
val = 0;
break;
case MT_SBISC: /* SBISC */
val = sbi_sc & SBISC_RD;
break;
case MT_SBIMT: /* SBIMT */
val = sbi_mt & SBIMT_RD;
break;
case MT_SBIER: /* SBIER */
val = sbi_er & SBIER_RD;
break;
case MT_SBITA: /* SBITA */
val = sbi_tmo;
break;
case MT_MBRK: /* MBRK */
val = wcs_mbrk & MBRK_RW;
break;
case MT_SID: /* SID */
val = VAX780_SID | VAX780_ECO | VAX780_PLANT | VAX780_SN;
break;
default:
RSVD_OPND_FAULT;
}
return val;
}
/* Write 780-specific IPR's */
void WriteIPR (int32 rg, int32 val)
{
switch (rg) {
case MT_ICCS: /* ICCS */
iccs_wr (val);
break;
case MT_NICR: /* NICR */
nicr_wr (val);
break;
case MT_TODR: /* TODR */
todr_wr (val);
break;
case MT_WCSA: /* WCSA */
wcs_addr = val & WCSA_RW;
break;
case MT_WCSD: /* WCSD */
wcs_data = val & WCSD_WR;
wcs_addr = (wcs_addr & ~WCSA_CTR) |
((wcs_addr + WCSA_CTR_INC) & WCSA_CTR);
if ((wcs_addr & WCSA_CTR) == WCSA_CTR_MAX)
wcs_addr = (wcs_addr & ~WCSA_ADDR) |
((wcs_addr + 1) & WCSA_ADDR);
break;
case MT_RXCS: /* RXCS */
rxcs_wr (val);
break;
case MT_RXDB: /* RXDB */
break;
case MT_TXCS: /* TXCS */
txcs_wr (val);
break;
case MT_TXDB: /* TXDB */
txdb_wr (val);
break;
case MT_SBIFS: /* SBIFS */
sbi_fs = (sbi_fs & ~SBIFS_WR) | (val & SBIFS_WR);
sbi_fs = sbi_fs & ~(val & SBIFS_W1C);
break;
case MT_SBISC: /* SBISC */
sbi_sc = (sbi_sc & ~(SBISC_LOCK|SBISC_WR)) | (val & SBISC_WR);
break;
case MT_SBIMT: /* SBIMT */
sbi_mt = (sbi_mt & ~SBIMT_WR) | (val & SBIMT_WR);
break;
case MT_SBIER: /* SBIER */
sbi_er = (sbi_er & ~SBIER_WR) | (val & SBIER_WR);
sbi_er = sbi_er & ~(val & SBIER_W1C);
if (val & SBIER_TMO) sbi_er = sbi_er & ~SBIER_TMOW1C;
if (val & SBIER_IBTMO) sbi_er = sbi_er & ~SBIER_IBTW1C;
if ((sbi_er & SBIER_CRDIE) && (sbi_er & SBIER_CRD))
crd_err = 1;
else crd_err = 0;
break;
case MT_SBIQC:
// tbd /* SBIQC */
break;
case MT_MBRK: /* MBRK */
wcs_mbrk = val & MBRK_RW;
break;
default:
RSVD_OPND_FAULT;
}
return;
}
/* ReadReg - read register space
Inputs:
pa = physical address
lnt = length (BWLQ) - ignored
Output:
longword of data
*/
int32 ReadReg (int32 pa, int32 lnt)
{
int32 nexus, val;
if (ADDR_IS_REG (pa)) { /* reg space? */
nexus = NEXUS_GETNEX (pa); /* get nexus */
if (nexusR[nexus] && /* valid? */
(nexusR[nexus] (&val, pa, lnt) == SCPE_OK)) {
SET_IRQL;
return val;
}
}
sbi_set_tmo (pa); /* timeout */
MACH_CHECK (MCHK_RD_F); /* machine check */
return 0;
}
/* WriteReg - write register space
Inputs:
pa = physical address
val = data to write, right justified in 32b longword
lnt = length (BWLQ)
Outputs:
none
*/
void WriteReg (int32 pa, int32 val, int32 lnt)
{
int32 nexus;
if (ADDR_IS_REG (pa)) { /* reg space? */
nexus = NEXUS_GETNEX (pa); /* get nexus */
if (nexusW[nexus] && /* valid? */
(nexusW[nexus] (val, pa, lnt) == SCPE_OK)) {
SET_IRQL;
return;
}
}
sbi_set_tmo (pa); /* timeout */
mem_err = 1; /* interrupt */
eval_int ();
return;
}
/* Set SBI timeout */
void sbi_set_tmo (int32 pa)
{
if ((sbi_er & SBIER_TMO) == 0) { /* not yet set? */
sbi_tmo = pa >> 2; /* save addr */
if (mchk_ref == REF_V) sbi_tmo |= SBITMO_VIRT | /* virt? add mode */
(PSL_GETCUR (PSL) << SBITMO_V_MODE);
sbi_er |= SBIER_TMO; } /* set tmo flag */
else sbi_er |= SBIER_MULT; /* yes, multiple */
return;
}
/* Memory controller register read */
t_stat mctl_rdreg (int32 *val, int32 pa, int32 mode)
{
int32 mctl, ofs;
mctl = NEXUS_GETNEX (pa) - TR_MCTL0; /* get mctl num */
ofs = NEXUS_GETOFS (pa); /* get offset */
if (ofs >= MCRROM_OF) { /* ROM? */
*val = rom_lw[mctl][ofs - MCRROM_OF]; /* get lw */
return SCPE_OK;
}
if (ofs >= MCRMAX_OF) return SCPE_NXM; /* in range? */
switch (ofs) {
case MCRA_OF: /* CR A */
*val = mcr_a[mctl] & MCRA_RD;
break;
case MCRB_OF: /* CR B */
*val = (mcr_b[mctl] & MCRB_RD) | MCRB_INIT;
break;
case MCRC_OF: /* CR C */
*val = mcr_c[mctl] & (cpu_extmem? MCRC_E_RD: MCRC_C_RD);
break;
case MCRD_OF: /* CR D */
if (!cpu_extmem) return SCPE_NXM; /* MS780E only */
*val = mcr_d[mctl] & MCRC_E_RD;
break;
}
return SCPE_OK;
}
/* Memory controller register write */
t_stat mctl_wrreg (int32 val, int32 pa, int32 mode)
{
int32 mctl, ofs, mask;
mctl = NEXUS_GETNEX (pa) - TR_MCTL0; /* get mctl num */
ofs = NEXUS_GETOFS (pa); /* get offset */
if (ofs >= MCRMAX_OF) return SCPE_NXM; /* in range? */
switch (ofs) {
case MCRA_OF: /* CR A */
mask = MCRA_WR | ((val & MCRA_ILVE)? MCRA_ILV: 0);
mcr_a[mctl] = (mcr_a[mctl] & ~mask) | (val & mask);
break;
case MCRB_OF: /* CR B */
mask = MCRB_WR | ((val & MCRB_SAE)? MCRB_SA: 0);
mcr_b[mctl] = (mcr_b[mctl] & ~mask) | (val & mask);
break;
case MCRC_OF: /* CR C */
mcr_c[mctl] = ((mcr_c[mctl] & MCRC_WR) | (val & MCRC_WR)) &
~(val & (cpu_extmem? MCRC_E_W1C: MCRC_C_W1C));
break;
case MCRD_OF: /* CR D */
if (!cpu_extmem) return SCPE_NXM; /* MS780E only */
mcr_d[mctl] = ((mcr_d[mctl] & MCRC_WR) | (val & MCRC_WR)) &
~(val & MCRC_E_W1C);
break;
}
return SCPE_OK;
}
/* Used by CPU and loader */
void rom_wr_B (int32 pa, int32 val)
{
uint32 mctl = NEXUS_GETNEX (pa) - TR_MCTL0; /* get mctl num */
uint32 ofs = NEXUS_GETOFS (pa) - MCRROM_OF; /* get offset */
int32 sc = (pa & 3) << 3;
rom_lw[mctl][ofs] = ((val & 0xFF) << sc) | (rom_lw[mctl][ofs] & ~(0xFF << sc));
return;
}
/* Machine check
Error status word format
<2:0> = ASTLVL
<3> = PME
<6:4> = arith trap code
Rest will be zero
*/
int32 machine_check (int32 p1, int32 opc, int32 cc)
{
int32 acc, err;
err = (GET_TRAP (trpirq) << 4) | (pme << 3) | ASTLVL; /* error word */
cc = intexc (SCB_MCHK, cc, 0, IE_SVE); /* take exception */
acc = ACC_MASK (KERN); /* in kernel mode */
in_ie = 1;
SP = SP - 44; /* push 11 words */
Write (SP, 40, L_LONG, WA); /* # bytes */
Write (SP + 4, p1, L_LONG, WA); /* mcheck type */
Write (SP + 8, err, L_LONG, WA); /* CPU error status */
Write (SP + 12, 0, L_LONG, WA); /* uPC */
Write (SP + 16, mchk_va, L_LONG, WA); /* VA */
Write (SP + 20, 0, L_LONG, WA); /* D register */
Write (SP + 24, mapen, L_LONG, WA); /* TB status 1 */
Write (SP + 28, 0, L_LONG, WA); /* TB status 2 */
Write (SP + 32, sbi_tmo, L_LONG, WA); /* SBI timeout addr */
Write (SP + 36, 0, L_LONG, WA); /* cache status */
Write (SP + 40, sbi_er, L_LONG, WA); /* SBI error */
in_ie = 0;
return cc;
}
/* Console entry */
int32 con_halt (int32 code, int32 cc)
{
ABORT (STOP_HALT);
return cc;
}
/* Special boot command - linked into SCP by initial reset
Syntax: BOOT <device>{/R5:val}
Sets up R0-R5, calls SCP boot processor with effective BOOT CPU
*/
t_stat vax780_boot (int32 flag, char *ptr)
{
char gbuf[CBUFSIZE];
char *slptr, *regptr;
int32 i, r5v, unitno;
DEVICE *dptr;
UNIT *uptr;
DIB *dibp;
t_stat r;
regptr = get_glyph (ptr, gbuf, 0); /* get glyph */
if (slptr = strchr (gbuf, '/')) { /* found slash? */
regptr = strchr (ptr, '/'); /* locate orig */
*slptr = 0; } /* zero in string */
dptr = find_unit (gbuf, &uptr); /* find device */
if ((dptr == NULL) || (uptr == NULL)) return SCPE_ARG;
dibp = (DIB *) dptr->ctxt; /* get DIB */
if (dibp == NULL) return SCPE_ARG;
unitno = uptr - dptr->units;
r5v = 0;
if ((strncmp (regptr, "/R5:", 4) == 0) ||
(strncmp (regptr, "/R5=", 4) == 0) ||
(strncmp (regptr, "/r5:", 4) == 0) ||
(strncmp (regptr, "/r5=", 4) == 0)) {
r5v = (int32) get_uint (regptr + 4, 16, LMASK, &r);
if (r != SCPE_OK) return r; }
else if (*regptr != 0) return SCPE_ARG;
for (i = 0; boot_tab[i].name != NULL; i++) {
if (strcmp (dptr->name, boot_tab[i].name) == 0) {
R[0] = boot_tab[i].code;
if (dptr->flags & DEV_MBUS) {
R[1] = dibp->ba + TR_MBA0;
R[2] = unitno;
}
else {
R[1] = TR_UBA;
R[2] = boot_tab[i].let | (dibp->ba & UBADDRMASK);
}
R[3] = unitno;
R[4] = 0;
R[5] = r5v;
return run_cmd (flag, "CPU");
}
}
return SCPE_NOFNC;
}
/* Bootstrap - finish up bootstrap process */
t_stat cpu_boot (int32 unitno, DEVICE *dptr)
{
t_stat r;
printf ("Loading boot code from vmb780.bin\n");
if (sim_log) fprintf (sim_log,
"Loading boot code from vmb780.bin\n");
r = load_cmd (0, "-O vmb780.bin 200");
if (r != SCPE_OK) return r;
SP = PC = 512;
return SCPE_OK;
}
/* SBI reset */
t_stat sbi_reset (DEVICE *dptr)
{
wcs_addr = 0;
wcs_data = 0;
wcs_mbrk = 0;
sbi_fs = 0;
sbi_sc = 0;
sbi_mt = 0;
sbi_er = 0;
sbi_tmo = 0;
sim_vm_cmd = vax780_cmd;
return SCPE_OK;
}
/* MEMCTL reset */
t_stat mctl_reset (DEVICE *dptr)
{
int32 i, amb;
amb = (MEMSIZE / 2) >> 20; /* array size MB */
for (i = 0; i < MCTL_NUM; i++) { /* init for MS780C */
if (cpu_extmem) { /* extended memory? */
mcr_a[i] = (amb << MCRA_V_SIZE) | MCRA_E_TYPE;
mcr_b[i] = MCRB_INIT | ((i * amb) << MCRB_V_SA);
}
else {
mcr_a[i] = MCRA_C_SIZE | MCRA_C_TYPE;
mcr_b[i] = MCRB_INIT | (i << 21);
}
mcr_c[i] = 0;
mcr_d[i] = 0;
}
return SCPE_OK;
}
/* Show nexus */
t_stat show_nexus (FILE *st, UNIT *uptr, int32 val, void *desc)
{
fprintf (st, "nexus=%d", val);
return SCPE_OK;
}
/* Init nexus tables */
void init_nexus_tab (void)
{
uint32 i;
for (i = 0; i < NEXUS_NUM; i++) {
nexusR[i] = NULL;
nexusW[i] = NULL;
}
return;
}
/* Build nexus tables
Inputs:
dptr = pointer to device
dibp = pointer to DIB
Outputs:
status
*/
t_stat build_nexus_tab (DEVICE *dptr, DIB *dibp)
{
uint32 idx;
if ((dptr == NULL) || (dibp == NULL)) return SCPE_IERR;
idx = dibp->ba;
if (idx >= NEXUS_NUM) return SCPE_IERR;
if ((nexusR[idx] && dibp->rd && /* conflict? */
(nexusR[idx] != dibp->rd)) ||
(nexusW[idx] && dibp->wr &&
(nexusW[idx] != dibp->wr))) {
printf ("Nexus %s conflict at %d\n",
sim_dname (dptr), dibp->ba);
if (sim_log) fprintf (sim_log,
"Nexus %s conflict at %d\n",
sim_dname (dptr), dibp->ba);
return SCPE_STOP;
}
if (dibp->rd) nexusR[idx] = dibp->rd; /* set rd dispatch */
if (dibp->wr) nexusW[idx] = dibp->wr; /* set wr dispatch */
return SCPE_OK;
}
/* Build dib_tab from device list */
t_stat build_dib_tab (void)
{
uint32 i;
DEVICE *dptr;
DIB *dibp;
t_stat r;
init_nexus_tab ();
init_ubus_tab ();
init_mbus_tab ();
for (i = 0; (dptr = sim_devices[i]) != NULL; i++) { /* loop thru dev */
dibp = (DIB *) dptr->ctxt; /* get DIB */
if (dibp && !(dptr->flags & DEV_DIS)) { /* defined, enabled? */
if (dptr->flags & DEV_NEXUS) { /* Nexus? */
if (r = build_nexus_tab (dptr, dibp)) /* add to dispatch table */
return r;
}
else if (dptr->flags & DEV_MBUS) { /* Massbus? */
if (r = build_mbus_tab (dptr, dibp))
return r;
}
else { /* no, Unibus device */
if (r = build_ubus_tab (dptr, dibp)) /* add to dispatch tab */
return r;
} /* end else */
} /* end if enabled */
} /* end for */
return SCPE_OK;
}

View file

@ -1,851 +0,0 @@
/* vax780_stddev.c: VAX 11/780 standard I/O devices
Copyright (c) 1998-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.
tti console input
tto console output
rx console floppy
todr TODR clock
tmr interval timer
08-Sep-04 RMS Cloned from vax_stddev.c, vax_sysdev.c, and pdp11_rx.c
The console floppy protocol is based on the description in the 1982 VAX
Architecture Reference Manual:
TXDB<11:8> = 0 -> normal console output
TXDB<11:8> = 1 -> data output to floppy
TXDB<11:8> = 9 -> command output to floppy
TXDB<11:8> = F -> flag output (e.g., reboot)
RXDB<11:8> = 0 -> normal terminal input
RXDB<11:8> = 1 -> data input from floppy
RXDB<11:8> = 2 -> status input from floppy
RXDB<11:8> = 9 -> "command" input from floppy (protocol error)
*/
#include "vax_defs.h"
#include <time.h>
/* Terminal definitions */
#define RXCS_RD (CSR_DONE + CSR_IE) /* terminal input */
#define RXCS_WR (CSR_IE)
#define RXDB_ERR 0x8000 /* error */
#define RXDB_OVR 0x4000 /* overrun */
#define RXDB_FRM 0x2000 /* framing error */
#define RXDB_RBR 0x0400 /* receive break */
#define TXCS_RD (CSR_DONE + CSR_IE) /* terminal output */
#define TXCS_WR (CSR_IE)
#define TXDB_V_SEL 8 /* unit select */
#define TXDB_M_SEL 0xF
#define TXDB_FDAT 0x1 /* floppy data */
#define TXDB_FCMD 0x9 /* floppy cmd */
#define TXDB_MISC 0xF /* console misc */
#define TXDB_SEL (TXDB_M_SEL << TXDB_V_SEL) /* non-terminal */
#define TXDB_GETSEL(x) (((x) >> TXDB_V_SEL) & TXDB_M_SEL)
#define UNIT_V_8B (UNIT_V_UF + 0) /* 8B mode */
#define UNIT_8B (1 << UNIT_V_8B)
/* Clock definitions */
#define TMR_CSR_ERR 0x80000000 /* error W1C */
#define TMR_CSR_DON 0x00000080 /* done W1C */
#define TMR_CSR_IE 0x00000040 /* int enb RW */
#define TMR_CSR_SGL 0x00000020 /* single WO */
#define TMR_CSR_XFR 0x00000010 /* xfer WO */
#define TMR_CSR_RUN 0x00000001 /* run RW */
#define TMR_CSR_RD (TMR_CSR_W1C | TMR_CSR_WR)
#define TMR_CSR_W1C (TMR_CSR_ERR | TMR_CSR_DON)
#define TMR_CSR_WR (TMR_CSR_IE | TMR_CSR_RUN)
#define TMR_INC 10000 /* usec/interval */
#define CLK_DELAY 5000 /* 100 Hz */
#define TMXR_MULT 2 /* 50 Hz */
/* Floppy definitions */
#define FL_NUMTR 77 /* tracks/disk */
#define FL_M_TRACK 0377
#define FL_NUMSC 26 /* sectors/track */
#define FL_M_SECTOR 0177
#define FL_NUMBY 128 /* bytes/sector */
#define FL_SIZE (FL_NUMTR * FL_NUMSC * FL_NUMBY) /* bytes/disk */
#define UNIT_V_WLK (UNIT_V_UF) /* write locked */
#define UNIT_WLK (1u << UNIT_V_UF)
#define UNIT_WPRT (UNIT_WLK | UNIT_RO) /* write protect */
#define FL_IDLE 0 /* idle state */
#define FL_RWDS 1 /* rw, sect next */
#define FL_RWDT 2 /* rw, track next */
#define FL_READ 3 /* read */
#define FL_READ1 4
#define FL_WRITE 5 /* write */
#define FL_WRITE1 6
#define FL_FILL 7 /* fill buffer */
#define FL_EMPTY 8 /* empty buffer */
#define FL_READSTA 9 /* read status */
#define FL_DONE 10 /* cmd done */
#define FL_V_FNC 0 /* floppy function */
#define FL_M_FNC 0xFF
#define FL_FNCRD 0x0 /* read */
#define FL_FNCWR 0x1 /* write */
#define FL_FNCRS 0x2 /* read status */
#define FL_FNCWD 0x3 /* write del data */
#define FL_FNCCA 0x4 /* cancel */
#define FL_CDATA 0x100 /* returned data */
#define FL_CDONE 0x200 /* completion code */
#define FL_STACRC 0x001 /* status bits */
#define FL_STAPAR 0x002
#define FL_STAINC 0x004
#define FL_STADDA 0x040
#define FL_STAERR 0x080
#define FL_CPROT 0x905 /* protocol error */
#define FL_MISC 0xF00 /* misc communications */
#define FL_SWDN 0x1 /* software done */
#define FL_BOOT 0x2 /* reboot */
#define FL_CLWS 0x3 /* clear warm start */
#define FL_CLCS 0x4 /* clear cold start */
#define FL_GETFNC(x) (((x) >> FL_V_FNC) & FL_M_FNC)
#define TRACK u3 /* current track */
#define CALC_DA(t,s) (((t) * FL_NUMSC) + ((s) - 1)) * FL_NUMBY
int32 tti_csr = 0; /* control/status */
int32 tti_buf = 0; /* buffer */
int32 tti_int = 0; /* interrupt */
int32 tto_csr = 0; /* control/status */
int32 tto_buf = 0; /* buffer */
int32 tto_int = 0; /* interrupt */
int32 tmr_iccs = 0; /* interval timer csr */
uint32 tmr_icr = 0; /* curr interval */
uint32 tmr_nicr = 0; /* next interval */
uint32 tmr_inc = 0; /* timer increment */
int32 tmr_sav = 0; /* timer save */
int32 tmr_int = 0; /* interrupt */
int32 clk_tps = 100; /* ticks/second */
int32 tmxr_poll = CLK_DELAY * TMXR_MULT; /* term mux poll */
int32 tmr_poll = CLK_DELAY; /* pgm timer poll */
int32 todr_reg = 0; /* TODR register */
int32 fl_fnc = 0; /* function */
int32 fl_esr = 0; /* error status */
int32 fl_ecode = 0; /* error code */
int32 fl_track = 0; /* desired track */
int32 fl_sector = 0; /* desired sector */
int32 fl_state = FL_IDLE; /* controller state */
int32 fl_stopioe = 1; /* stop on error */
int32 fl_swait = 100; /* seek, per track */
int32 fl_cwait = 50; /* command time */
int32 fl_xwait = 20; /* tr set time */
uint8 fl_buf[FL_NUMBY] = { 0 }; /* sector buffer */
int32 fl_bptr = 0; /* buffer pointer */
extern int32 sim_switches;
t_stat tti_svc (UNIT *uptr);
t_stat tto_svc (UNIT *uptr);
t_stat clk_svc (UNIT *uptr);
t_stat tmr_svc (UNIT *uptr);
t_stat tti_reset (DEVICE *dptr);
t_stat tto_reset (DEVICE *dptr);
t_stat clk_reset (DEVICE *dptr);
t_stat tmr_reset (DEVICE *dptr);
t_stat fl_svc (UNIT *uptr);
t_stat fl_reset (DEVICE *dptr);
int32 icr_rd (t_bool interp);
void tmr_incr (uint32 inc);
void tmr_sched (void);
t_stat todr_powerup (void);
t_stat fl_wr_txdb (int32 data);
t_bool fl_test_xfr (UNIT *uptr, t_bool wr);
void fl_protocol_error (void);
/* TTI data structures
tti_dev TTI device descriptor
tti_unit TTI unit descriptor
tti_reg TTI register list
*/
UNIT tti_unit = { UDATA (&tti_svc, UNIT_8B, 0), KBD_POLL_WAIT };
REG tti_reg[] = {
{ HRDATA (RXDB, tti_buf, 16) },
{ HRDATA (RXCS, tti_csr, 16) },
{ FLDATA (INT, tti_int, 0) },
{ FLDATA (DONE, tti_csr, CSR_V_DONE) },
{ FLDATA (IE, tti_csr, CSR_V_IE) },
{ DRDATA (POS, tti_unit.pos, T_ADDR_W), PV_LEFT },
{ DRDATA (TIME, tti_unit.wait, 24), REG_NZ + PV_LEFT },
{ NULL } };
MTAB tti_mod[] = {
{ UNIT_8B, UNIT_8B, "8b", "8B", NULL },
{ UNIT_8B, 0 , "7b", "7B", NULL },
{ 0 } };
DEVICE tti_dev = {
"TTI", &tti_unit, tti_reg, tti_mod,
1, 10, 31, 1, 16, 8,
NULL, NULL, &tti_reset,
NULL, NULL, NULL,
NULL, 0 };
/* TTO data structures
tto_dev TTO device descriptor
tto_unit TTO unit descriptor
tto_reg TTO register list
*/
UNIT tto_unit = { UDATA (&tto_svc, UNIT_8B, 0), SERIAL_OUT_WAIT };
REG tto_reg[] = {
{ HRDATA (TXDB, tto_buf, 16) },
{ HRDATA (TXCS, tto_csr, 16) },
{ FLDATA (INT, tto_int, 0) },
{ FLDATA (DONE, tto_csr, CSR_V_DONE) },
{ FLDATA (IE, tto_csr, CSR_V_IE) },
{ DRDATA (POS, tto_unit.pos, T_ADDR_W), PV_LEFT },
{ DRDATA (TIME, tto_unit.wait, 24), PV_LEFT },
{ NULL } };
MTAB tto_mod[] = {
{ UNIT_8B, UNIT_8B, "8b", "8B", NULL },
{ UNIT_8B, 0 , "7b", "7B", NULL },
{ 0 } };
DEVICE tto_dev = {
"TTO", &tto_unit, tto_reg, tto_mod,
1, 10, 31, 1, 16, 8,
NULL, NULL, &tto_reset,
NULL, NULL, NULL,
NULL, 0 };
/* TODR and TMR data structures */
UNIT clk_unit = { UDATA (&clk_svc, 0, 0), CLK_DELAY }; /* 100Hz */
REG clk_reg[] = {
{ DRDATA (TODR, todr_reg, 32), PV_LEFT },
{ DRDATA (TIME, clk_unit.wait, 24), REG_NZ + PV_LEFT },
{ DRDATA (TPS, clk_tps, 8), REG_HIDDEN + REG_NZ + PV_LEFT },
{ NULL } };
DEVICE clk_dev = {
"TODR", &clk_unit, clk_reg, NULL,
1, 0, 0, 0, 0, 0,
NULL, NULL, &clk_reset,
NULL, NULL, NULL,
NULL, 0 };
UNIT tmr_unit = { UDATA (&tmr_svc, 0, 0) }; /* timer */
REG tmr_reg[] = {
{ HRDATA (ICCS, tmr_iccs, 32) },
{ HRDATA (ICR, tmr_icr, 32) },
{ HRDATA (NICR, tmr_nicr, 32) },
{ HRDATA (INCR, tmr_inc, 32), REG_HIDDEN },
{ HRDATA (SAVE, tmr_sav, 32), REG_HIDDEN },
{ FLDATA (INT, tmr_int, 0) },
{ NULL } };
DEVICE tmr_dev = {
"TMR", &tmr_unit, tmr_reg, NULL,
1, 0, 0, 0, 0, 0,
NULL, NULL, &tmr_reset,
NULL, NULL, NULL,
NULL, 0 };
/* RX01 data structures
fl_dev RX device descriptor
fl_unit RX unit list
fl_reg RX register list
fl_mod RX modifier list
*/
UNIT fl_unit = { UDATA (&fl_svc,
UNIT_FIX+UNIT_ATTABLE+UNIT_BUFABLE+UNIT_MUSTBUF, FL_SIZE) };
REG fl_reg[] = {
{ HRDATA (FNC, fl_fnc, 8) },
{ HRDATA (ES, fl_esr, 8) },
{ HRDATA (ECODE, fl_ecode, 8) },
{ HRDATA (TA, fl_track, 8) },
{ HRDATA (SA, fl_sector, 8) },
{ DRDATA (STATE, fl_state, 4), REG_RO },
{ DRDATA (BPTR, fl_bptr, 7) },
{ DRDATA (CTIME, fl_cwait, 24), PV_LEFT },
{ DRDATA (STIME, fl_swait, 24), PV_LEFT },
{ DRDATA (XTIME, fl_xwait, 24), PV_LEFT },
{ FLDATA (STOP_IOE, fl_stopioe, 0) },
{ BRDATA (DBUF, fl_buf, 16, 8, FL_NUMBY) },
{ NULL } };
MTAB fl_mod[] = {
{ UNIT_WLK, 0, "write enabled", "WRITEENABLED", NULL },
{ UNIT_WLK, UNIT_WLK, "write locked", "LOCKED", NULL },
{ 0 } };
DEVICE fl_dev = {
"RX", &fl_unit, fl_reg, fl_mod,
1, DEV_RDX, 20, 1, DEV_RDX, 8,
NULL, NULL, &fl_reset,
NULL, NULL, NULL,
NULL, 0 };
/* Terminal MxPR routines
rxcs_rd/wr input control/status
rxdb_rd input buffer
txcs_rd/wr output control/status
txdb_wr output buffer
*/
int32 rxcs_rd (void)
{
return (tti_csr & RXCS_RD);
}
void rxcs_wr (int32 data)
{
if ((data & CSR_IE) == 0) tto_int = 0;
else if ((tti_csr & (CSR_DONE + CSR_IE)) == CSR_DONE)
tti_int = 1;
tti_csr = (tti_csr & ~RXCS_WR) | (data & RXCS_WR);
return;
}
int32 rxdb_rd (void)
{
int32 t = tti_buf; /* char + error */
tti_csr = tti_csr & ~CSR_DONE; /* clr done */
tti_buf = tti_buf & BMASK; /* clr errors */
tti_int = 0;
return t;
}
int32 txcs_rd (void)
{
return (tto_csr & TXCS_RD);
}
void txcs_wr (int32 data)
{
if ((data & CSR_IE) == 0) tto_int = 0;
else if ((tto_csr & (CSR_DONE + CSR_IE)) == CSR_DONE)
tto_int = 1;
tto_csr = (tto_csr & ~TXCS_WR) | (data & TXCS_WR);
return;
}
void txdb_wr (int32 data)
{
tto_buf = data & WMASK; /* save data */
tto_csr = tto_csr & ~CSR_DONE; /* clear flag */
tto_int = 0; /* clear int */
if (tto_buf & TXDB_SEL) fl_wr_txdb (tto_buf); /* floppy? */
else sim_activate (&tto_unit, tto_unit.wait); /* no, console */
return;
}
/* Terminal input service (poll for character */
t_stat tti_svc (UNIT *uptr)
{
int32 c;
sim_activate (&tti_unit, tti_unit.wait); /* continue poll */
if ((c = sim_poll_kbd ()) < SCPE_KFLAG) return c; /* no char or error? */
if (c & SCPE_BREAK) /* break? */
tti_buf = RXDB_ERR | RXDB_FRM | RXDB_RBR;
else tti_buf = c & ((tti_unit.flags & UNIT_8B)? 0377: 0177);
tti_unit.pos = tti_unit.pos + 1;
tti_csr = tti_csr | CSR_DONE;
if (tti_csr & CSR_IE) tti_int = 1;
return SCPE_OK;
}
/* Terminal input reset */
t_stat tti_reset (DEVICE *dptr)
{
tti_buf = 0;
tti_csr = 0;
tti_int = 0;
sim_activate (&tti_unit, tti_unit.wait); /* activate unit */
return SCPE_OK;
}
/* Terminal output service (output character) */
t_stat tto_svc (UNIT *uptr)
{
int32 c;
t_stat r;
if ((tto_buf & TXDB_SEL) == 0) { /* for console? */
c = tto_buf & ((tto_unit.flags & UNIT_8B)? 0377: 0177);
if ((r = sim_putchar_s (c)) != SCPE_OK) { /* output; error? */
sim_activate (uptr, uptr->wait); /* retry */
return ((r == SCPE_STALL)? SCPE_OK: r); } /* !stall? report */
tto_unit.pos = tto_unit.pos + 1; }
tto_csr = tto_csr | CSR_DONE;
if (tto_csr & CSR_IE) tto_int = 1;
return SCPE_OK;
}
/* Terminal output reset */
t_stat tto_reset (DEVICE *dptr)
{
tto_buf = 0;
tto_csr = CSR_DONE;
tto_int = 0;
sim_cancel (&tto_unit); /* deactivate unit */
return SCPE_OK;
}
/* Programmable timer
The architected VAX timer, which increments at 1Mhz, cannot be
accurately simulated due to the overhead that would be required
for 1M clock events per second. Instead, a hidden calibrated
100Hz timer is run (because that's what VMS expects), and a
gross hack is used for the interval timer.
When the timer is started, the timer interval is inspected.
if (int < 0 and small) then testing timer, count instructions.
Small is determined by when the requested interval is less
than the size of a 100Hz system clock tick.
if (int >= 0 or large) then counting a real interval, schedule
clock events at 100Hz using calibrated clock delay. When
the remaining time value gets small enough, behave like
the small case above.
If the interval register is read, then its value between events
is interpolated using the current instruction count versus the
count when the most recent event started, the result is scaled
to the calibrated system clock, unless the interval being timed
is less than a calibrated system clock tick (or the calibrated
clock is running very slowly) at which time the result will be
the elapsed instruction count.
*/
int32 iccs_rd (void)
{
return tmr_iccs & TMR_CSR_RD;
}
void iccs_wr (int32 val)
{
if ((val & TMR_CSR_RUN) == 0) { /* clearing run? */
sim_cancel (&tmr_unit); /* cancel timer */
if (tmr_iccs & TMR_CSR_RUN) /* run 1 -> 0? */
tmr_icr = icr_rd (TRUE); } /* update itr */
tmr_iccs = tmr_iccs & ~(val & TMR_CSR_W1C); /* W1C csr */
tmr_iccs = (tmr_iccs & ~TMR_CSR_WR) | /* new r/w */
(val & TMR_CSR_WR);
if (val & TMR_CSR_XFR) tmr_icr = tmr_nicr; /* xfr set? */
if (val & TMR_CSR_RUN) { /* run? */
if (val & TMR_CSR_XFR) /* new tir? */
sim_cancel (&tmr_unit); /* stop prev */
if (!sim_is_active (&tmr_unit)) /* not running? */
tmr_sched (); } /* activate */
else if (val & TMR_CSR_SGL) { /* single step? */
tmr_incr (1); /* incr tmr */
if (tmr_icr == 0) /* if ovflo, */
tmr_icr = tmr_nicr; } /* reload tir */
if ((tmr_iccs & (TMR_CSR_DON | TMR_CSR_IE)) != /* update int */
(TMR_CSR_DON | TMR_CSR_IE)) tmr_int = 0;
return;
}
int32 icr_rd (t_bool interp)
{
uint32 delta;
if (interp || (tmr_iccs & TMR_CSR_RUN)) { /* interp, running? */
delta = sim_grtime () - tmr_sav; /* delta inst */
if ((tmr_inc == TMR_INC) && /* scale large int */
(tmr_poll > TMR_INC))
delta = (uint32) ((((double) delta) * TMR_INC) / tmr_poll);
if (delta >= tmr_inc) delta = tmr_inc - 1;
return tmr_icr + delta; }
return tmr_icr;
}
int32 nicr_rd ()
{
return tmr_nicr;
}
void nicr_wr (int32 val)
{
tmr_nicr = val;
}
/* 100Hz base clock unit service */
t_stat clk_svc (UNIT *uptr)
{
int32 t;
t = sim_rtcn_calb (clk_tps, TMR_CLK); /* calibrate clock */
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 */
return SCPE_OK;
}
/* Interval timer unit service */
t_stat tmr_svc (UNIT *uptr)
{
tmr_incr (tmr_inc); /* incr timer */
return SCPE_OK;
}
/* Timer increment */
void tmr_incr (uint32 inc)
{
uint32 new_icr = (tmr_icr + inc) & LMASK; /* add incr */
if (new_icr < tmr_icr) { /* ovflo? */
tmr_icr = 0; /* now 0 */
if (tmr_iccs & TMR_CSR_DON) /* done? set err */
tmr_iccs = tmr_iccs | TMR_CSR_ERR;
else tmr_iccs = tmr_iccs | TMR_CSR_DON; /* set done */
if (tmr_iccs & TMR_CSR_RUN) { /* run? */
tmr_icr = tmr_nicr; /* reload */
tmr_sched (); } /* reactivate */
if (tmr_iccs & TMR_CSR_IE) tmr_int = 1; /* ie? set int req */
else tmr_int = 0; }
else { tmr_icr = new_icr; /* no, update icr */
if (tmr_iccs & TMR_CSR_RUN) /* still running? */
tmr_sched (); } /* reactivate */
return;
}
/* Timer scheduling */
void tmr_sched (void)
{
int32 clk_time = sim_is_active (&clk_unit) - 1;
int32 tmr_time;
tmr_sav = sim_grtime (); /* save intvl base */
if (tmr_icr > (0xFFFFFFFFu - TMR_INC)) { /* short interval? */
tmr_inc = (~tmr_icr + 1); /* inc = interval */
tmr_time = tmr_inc; }
else { tmr_inc = TMR_INC; /* usec/interval */
tmr_time = tmr_poll; }
if (tmr_time == 0) tmr_time = 1;
if ((tmr_inc = TMR_INC) && (tmr_time > clk_time)) {
/* Align scheduled event to be identical to the event for the next clock
tick. This lets us always see a consistent calibrated value, both for
this scheduling, AND for any query of the current timer register that
may happen in tmr_icr_rd (). This presumes that sim_activate will
queue the interval timer behind the event for the 100Hz clock tick. */
tmr_inc = (uint32) (((double) clk_time * TMR_INC) / tmr_poll);
tmr_time = clk_time; }
sim_activate (&tmr_unit, tmr_time);
return;
}
/* 100Hz clock reset */
t_stat clk_reset (DEVICE *dptr)
{
int32 t;
t = sim_rtcn_init (clk_unit.wait, TMR_CLK); /* init 100Hz timer */
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;
}
/* Interval timer reset */
t_stat tmr_reset (DEVICE *dptr)
{
tmr_iccs = 0;
tmr_icr = 0;
tmr_nicr = 0;
tmr_int = 0;
sim_cancel (&tmr_unit); /* cancel timer */
if (sim_switches & SWMASK ('P')) todr_powerup (); /* powerup? set TODR */
return SCPE_OK;
}
/* TODR routines */
int32 todr_rd (void)
{
return todr_reg;
}
void todr_wr (int32 data)
{
todr_reg = data;
return;
}
t_stat todr_powerup (void)
{
uint32 base;
time_t curr;
struct tm *ctm;
curr = time (NULL); /* get curr time */
if (curr == (time_t) -1) return SCPE_NOFNC; /* error? */
ctm = localtime (&curr); /* decompose */
if (ctm == NULL) return SCPE_NOFNC; /* error? */
base = (((((ctm->tm_yday * 24) + /* sec since 1-Jan */
ctm->tm_hour) * 60) +
ctm->tm_min) * 60) +
ctm->tm_sec;
todr_reg = (base * 100) + 0x10000000; /* cvt to VAX form */
return SCPE_OK;
}
/* Console write, txdb<11:8> != 0 (console unit) */
t_stat fl_wr_txdb (int32 data)
{
int32 sel = TXDB_GETSEL (data); /* get selection */
if (sel == TXDB_FCMD) { /* floppy command? */
fl_fnc = FL_GETFNC (data); /* get function */
if (fl_state != FL_IDLE) switch (fl_fnc) { /* cmd in prog? */
case FL_FNCCA: /* cancel? */
sim_cancel (&fl_unit); /* stop op */
fl_state = FL_DONE;
break;
default: /* all others */
fl_protocol_error ();
return SCPE_OK;
}
else switch (fl_fnc) { /* idle, case */
case FL_FNCRS: /* read status */
fl_state = FL_READSTA;
break;
case FL_FNCCA: /* cancel, nop */
fl_state = FL_DONE;
break;
case FL_FNCRD: case FL_FNCWR: /* data xfer */
case FL_FNCWD:
fl_esr = 0; /* clear errors */
fl_ecode = 0;
fl_bptr = 0; /* init buffer */
fl_state = FL_RWDS; /* sector next */
break;
default: /* all others */
fl_protocol_error ();
return SCPE_OK;
}
sim_activate (&fl_unit, fl_cwait); /* sched command */
} /* end command */
else if (sel == TXDB_FDAT) { /* floppy data? */
switch (fl_state) { /* data */
case FL_RWDS: /* expecting sector */
fl_sector = data & FL_M_SECTOR;
fl_state = FL_RWDT;
break;
case FL_RWDT: /* expecting track */
fl_track = data & FL_M_TRACK;
if (fl_fnc == FL_FNCRD) fl_state = FL_READ;
else fl_state = FL_FILL;
break;
case FL_FILL: /* expecting wr data */
fl_buf[fl_bptr++] = data & BMASK;
if (fl_bptr >= FL_NUMBY) fl_state = FL_WRITE;
break;
default:
fl_protocol_error ();
return SCPE_OK;
}
sim_activate (&fl_unit, fl_xwait); /* schedule xfer */
} /* end else data */
else sim_activate (&tto_unit, tto_unit.wait); /* discard for now */
return SCPE_OK;
}
/* Unit service; the action to be taken depends on the transfer state:
FL_IDLE Should never get here
FL_RWDS Set TXCS<done> (driver sends sector, sets FL_RWDT)
FL_RWDT Set TXCS<done> (driver sends track, sets FL_READ/FL_FILL)
FL_READ Set TXCS<done>, schedule FL_READ1
FL_READ1 Read sector, schedule FL_EMPTY
FL_EMPTY Copy data to RXDB, set RXCS<done>
if fl_bptr >= max, schedule completion, else continue
FL_FILL Set TXCS<done> (driver sends next byte, sets FL_WRITE)
FL_WRITE Set TXCS<done>, schedule FL_WRITE1
FL_WRITE1 Write sector, schedule FL_DONE
FL_DONE Copy requested data to TXDB, set FL_IDLE
*/
t_stat fl_svc (UNIT *uptr)
{
int32 i, t;
uint32 da;
int8 *fbuf = uptr->filebuf;
switch (fl_state) { /* case on state */
case FL_IDLE: /* idle */
return SCPE_IERR; /* done */
case FL_READ: case FL_WRITE: /* read, write */
fl_state = fl_state + 1; /* set next state */
t = abs (fl_track - uptr->TRACK); /* # tracks to seek */
if (t == 0) t = 1; /* minimum 1 */
sim_activate (uptr, fl_swait * t); /* schedule seek */
/* fall thru, set flag */
case FL_RWDS: case FL_RWDT: case FL_FILL: /* rwds, rwdt, fill */
tto_csr = tto_csr | CSR_DONE; /* set output done */
if (tto_csr & CSR_IE) tto_int = 1;
break;
case FL_READ1: /* read, seek done */
if (fl_test_xfr (uptr, FALSE)) { /* transfer ok? */
da = CALC_DA (fl_track, fl_sector); /* get disk address */
for (i = 0; i < FL_NUMBY; i++) /* copy sector to buf */
fl_buf[i] = fbuf[da + i];
tti_buf = fl_esr | FL_CDONE; /* completion code */
tti_csr = tti_csr | CSR_DONE; /* set input flag */
if (tti_csr & CSR_IE) tti_int = 1;
fl_state = FL_EMPTY; } /* go empty */
else fl_state = FL_DONE; /* error? cmd done */
sim_activate (uptr, fl_xwait); /* schedule next */
break;
case FL_EMPTY: /* empty buffer */
if ((tti_csr & CSR_DONE) == 0) { /* prev data taken? */
tti_buf = FL_CDATA | fl_buf[fl_bptr++]; /* get next byte */
tti_csr = tti_csr | CSR_DONE; /* set input flag */
if (tti_csr & CSR_IE) tti_int = 1;
if (fl_bptr >= FL_NUMBY) { /* buffer empty? */
fl_state = FL_IDLE; /* cmd done */
break;
}
}
sim_activate (uptr, fl_xwait); /* schedule next */
break;
case FL_WRITE1: /* write, seek done */
if (fl_test_xfr (uptr, TRUE)) { /* transfer ok? */
da = CALC_DA (fl_track, fl_sector); /* get disk address */
for (i = 0; i < FL_NUMBY; i++) /* copy buf to sector */
fbuf[da + i] = fl_buf[i];
da = da + FL_NUMBY;
if (da > uptr->hwmark) uptr->hwmark = da; /* update hwmark */
}
if (fl_fnc == FL_FNCWD) fl_esr |= FL_STADDA; /* wrdel? set status*/
fl_state = FL_DONE; /* command done */
sim_activate (uptr, fl_xwait); /* schedule */
break;
case FL_DONE: /* command done */
if (tti_csr & CSR_DONE) /* input buf empty? */
sim_activate (uptr, fl_xwait); /* no, wait */
else { /* yes */
tti_buf = fl_esr | FL_CDONE; /* completion code */
tti_csr = tti_csr | CSR_DONE; /* set input flag */
if (tti_csr & CSR_IE) tti_int = 1;
fl_state = FL_IDLE; /* floppy idle */
}
break;
case FL_READSTA: /* read status */
if ((tti_csr & CSR_DONE) == 0) { /* input buf empty? */
tti_buf = fl_ecode; /* return err code */
tti_csr = tti_csr | CSR_DONE; /* set input flag */
if (tti_csr & CSR_IE) tti_int = 1;
fl_state = FL_DONE; /* command done */
}
sim_activate (uptr, fl_xwait);
break;
}
return SCPE_OK;
}
/* Test for data transfer okay */
t_bool fl_test_xfr (UNIT *uptr, t_bool wr)
{
if ((uptr->flags & UNIT_BUF) == 0) /* not buffered? */
fl_ecode = 0110;
else if (fl_track >= FL_NUMTR) /* bad track? */
fl_ecode = 0040; /* done, error */
else if ((fl_sector == 0) || (fl_sector > FL_NUMSC)) /* bad sect? */
fl_ecode = 0070; /* done, error */
else if (wr && (uptr->flags & UNIT_WPRT)) /* write and locked? */
fl_ecode = 0100; /* done, error */
else { uptr->TRACK = fl_track; /* now on track */
return TRUE; }
fl_esr = fl_esr | FL_STAERR; /* set error */
return FALSE;
}
/* Set protocol error */
void fl_protocol_error (void)
{
if ((tto_csr & CSR_DONE) == 0) { /* output busy? */
tto_csr = tto_csr | CSR_DONE; /* set done */
if (tto_csr & CSR_IE) tto_int = 1; }
if ((tti_csr & CSR_DONE) == 0) { /* input idle? */
tti_csr = tti_csr | CSR_DONE; /* set done */
if (tti_csr & CSR_IE) tti_int = 1; }
tti_buf = FL_CPROT; /* status */
fl_state = FL_IDLE; /* floppy idle */
return;
}
/* Reset */
t_stat fl_reset (DEVICE *dptr)
{
fl_esr = FL_STAINC;
fl_ecode = 0; /* clear error */
fl_sector = 0; /* clear addr */
fl_track = 0;
fl_state = FL_IDLE; /* ctrl idle */
fl_bptr = 0;
sim_cancel (&fl_unit); /* cancel drive */
fl_unit.TRACK = 0;
return SCPE_OK;
}

View file

@ -1,130 +0,0 @@
/* vax_syslist.c: VAX device list
Copyright (c) 1998-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.
01-Oct-2004 RMS Cloned from vax_sys.c
*/
#include "vax_defs.h"
char sim_name[] = "VAX780 (pre-Beta developers preview)";
extern DEVICE cpu_dev;
extern DEVICE tlb_dev;
extern DEVICE sbi_dev;
extern DEVICE mctl0_dev, mctl1_dev;
extern DEVICE uba_dev;
extern DEVICE mba0_dev, mba1_dev;
extern DEVICE clk_dev;
extern DEVICE tmr_dev;
extern DEVICE tti_dev, tto_dev;
extern DEVICE fl_dev;
extern DEVICE lpt_dev;
extern DEVICE rq_dev, rqb_dev, rqc_dev, rqd_dev;
extern DEVICE rl_dev;
extern DEVICE hk_dev;
extern DEVICE rp_dev;
extern DEVICE ry_dev;
extern DEVICE ts_dev;
extern DEVICE tq_dev;
extern DEVICE tu_dev;
extern DEVICE dz_dev;
extern DEVICE xu_dev, xub_dev;
extern int32 sim_switches;
extern UNIT cpu_unit;
extern void WriteB (int32 pa, int32 val);
extern void rom_wr_B (int32 pa, int32 val);
DEVICE *sim_devices[] = {
&cpu_dev,
&tlb_dev,
&sbi_dev,
&mctl0_dev,
&mctl1_dev,
&uba_dev,
&mba0_dev,
&mba1_dev,
&clk_dev,
&tmr_dev,
&tti_dev,
&tto_dev,
&fl_dev,
&dz_dev,
&lpt_dev,
&rp_dev,
&rl_dev,
&hk_dev,
&rq_dev,
&rqb_dev,
&rqc_dev,
&rqd_dev,
&ry_dev,
&tu_dev,
&ts_dev,
&tq_dev,
&xu_dev,
&xub_dev,
NULL };
/* Binary loader
The binary loader handles absolute system images, that is, system
images linked /SYSTEM. These are simply a byte stream, with no
origin or relocation information.
-r load ROM0
-s load ROM1
-o for memory, specify origin
*/
t_stat sim_load (FILE *fileref, char *cptr, char *fnam, int flag)
{
t_stat r;
int32 val;
uint32 origin, limit;
if (flag) return SCPE_ARG; /* dump? */
origin = 0; /* memory */
limit = (uint32) cpu_unit.capac;
if (sim_switches & SWMASK ('O')) { /* origin? */
origin = (int32) get_uint (cptr, 16, 0xFFFFFFFF, &r);
if (r != SCPE_OK) return SCPE_ARG; }
while ((val = getc (fileref)) != EOF) { /* read byte stream */
if (sim_switches & SWMASK ('R')) { /* ROM0? */
if (origin >= ROMSIZE) return SCPE_NXM;
rom_wr_B (ROM0BASE + origin, val); }
else if (sim_switches & SWMASK ('S')) { /* ROM1? */
if (origin >= ROMSIZE) return SCPE_NXM;
rom_wr_B (ROM1BASE + origin, val); }
else {
if (origin >= limit) return SCPE_NXM; /* NXM? */
WriteB (origin, val); } /* memory */
origin = origin + 1; }
return SCPE_OK;
}

File diff suppressed because it is too large Load diff

View file

@ -408,8 +408,8 @@ case CRC:
*/
case MOVP:
if (PSL & PSL_FPD) RSVD_INST_FAULT;
if (op[0] > 31) RSVD_OPND_FAULT;
if ((PSL & PSL_FPD) || (op[0] > 31))
RSVD_OPND_FAULT;
ReadDstr (op[0], op[1], &dst, acc); /* read source */
cc = WriteDstr (op[0], op[2], &dst, 0, acc) | /* write dest */
(cc & CC_C); /* preserve C */
@ -445,8 +445,8 @@ case ADDP4: case SUBP4:
op[4] = op[2]; /* copy dst */
op[5] = op[3];
case ADDP6: case SUBP6:
if (PSL & PSL_FPD) RSVD_INST_FAULT;
if ((op[0] > 31) || (op[2] > 31) || (op[4] > 31))
if ((PSL & PSL_FPD) || (op[0] > 31) ||
(op[2] > 31) || (op[4] > 31))
RSVD_OPND_FAULT;
ReadDstr (op[0], op[1], &src1, acc); /* get src1 */
ReadDstr (op[2], op[3], &src2, acc); /* get src2 */
@ -498,8 +498,8 @@ case ADDP6: case SUBP6:
*/
case MULP:
if (PSL & PSL_FPD) RSVD_INST_FAULT;
if ((op[0] > 31) || (op[2] > 31) || (op[4] > 31))
if ((PSL & PSL_FPD) || (op[0] > 31) ||
(op[2] > 31) || (op[4] > 31))
RSVD_OPND_FAULT;
dst = Dstr_zero; /* clear result */
if (ReadDstr (op[0], op[1], &src1, acc) && /* read src1, src2 */
@ -548,8 +548,8 @@ case MULP:
*/
case DIVP:
if (PSL & PSL_FPD) RSVD_INST_FAULT;
if ((op[0] > 31) || (op[2] > 31) || (op[4] > 31))
if ((PSL & PSL_FPD) || (op[0] > 31) ||
(op[2] > 31) || (op[4] > 31))
RSVD_OPND_FAULT;
ldivr = ReadDstr (op[0], op[1], &src1, acc); /* get divisor */
if (ldivr == 0) { /* divisor = 0? */
@ -613,8 +613,8 @@ case CMPP3:
op[3] = op[2]; /* reposition ops */
op[2] = op[0];
case CMPP4:
if (PSL & PSL_FPD) RSVD_INST_FAULT;
if ((op[0] > 31) || (op[2] > 31)) RSVD_OPND_FAULT;
if ((PSL & PSL_FPD) || (op[0] > 31) || (op[2] > 31))
RSVD_OPND_FAULT;
ReadDstr (op[0], op[1], &src1, acc); /* get src1 */
ReadDstr (op[1], op[2], &src2, acc); /* get src2 */
cc = 0;
@ -651,8 +651,8 @@ case CMPP4:
*/
case ASHP:
if (PSL & PSL_FPD) RSVD_INST_FAULT;
if ((op[1] > 31) || (op[4] > 31)) RSVD_OPND_FAULT;
if ((PSL & PSL_FPD) || (op[1] > 31) || (op[4] > 31))
RSVD_OPND_FAULT;
ReadDstr (op[1], op[2], &src1, acc); /* get source */
V = 0; /* init V */
shift = op[0]; /* get shift count */
@ -695,8 +695,8 @@ case ASHP:
*/
case CVTPL:
if (PSL & PSL_FPD) RSVD_INST_FAULT;
if (op[0] > 31) RSVD_OPND_FAULT;
if ((PSL & PSL_FPD) || (op[0] > 31))
RSVD_OPND_FAULT;
ReadDstr (op[0], op[1], &src1, acc); /* get source */
V = result = 0; /* clear V, result */
for (i = (DSTRLNT * 8) - 1; i > 0; i--) { /* loop thru digits */
@ -737,8 +737,8 @@ case CVTPL:
*/
case CVTLP:
if (PSL & PSL_FPD) RSVD_INST_FAULT;
if (op[1] > 31) RSVD_OPND_FAULT;
if ((PSL & PSL_FPD) || (op[1] > 31))
RSVD_OPND_FAULT;
dst = Dstr_zero; /* clear result */
result = op[0];
if ((result & LSIGN) != 0) {
@ -775,8 +775,8 @@ case CVTLP:
*/
case CVTSP:
if (PSL & PSL_FPD) RSVD_INST_FAULT;
if ((op[0] > 31) || (op[2] > 31)) RSVD_OPND_FAULT;
if ((PSL & PSL_FPD) || (op[0] > 31) || (op[2] > 31))
RSVD_OPND_FAULT;
dst = Dstr_zero; /* clear result */
t = Read (op[1], L_BYTE, RA); /* read source sign */
if (t == C_MINUS) dst.sign = 1; /* sign -, */
@ -815,8 +815,8 @@ case CVTSP:
*/
case CVTPS:
if (PSL & PSL_FPD) RSVD_INST_FAULT;
if ((op[0] > 31) || (op[2] > 31)) RSVD_OPND_FAULT;
if ((PSL & PSL_FPD) || (op[0] > 31) || (op[2] > 31))
RSVD_OPND_FAULT;
ReadDstr (op[0], op[1], &dst, acc); /* get src */
ProbeDstr (op[2], op[3], WA); /* test dst write */
Write (op[3], dst.sign? C_MINUS: C_PLUS, L_BYTE, WA);
@ -851,8 +851,8 @@ case CVTPS:
*/
case CVTTP:
if (PSL & PSL_FPD) RSVD_INST_FAULT;
if ((op[0] > 31) || (op[3] > 31)) RSVD_OPND_FAULT;
if ((PSL & PSL_FPD) || (op[0] > 31) || (op[3] > 31))
RSVD_OPND_FAULT;
dst = Dstr_zero; /* clear result */
for (i = 1; i <= op[0]; i++) { /* loop thru char */
c = Read ((op[1] + op[0] - i) & LMASK, L_BYTE, RA); /* read char */
@ -897,17 +897,17 @@ case CVTTP:
*/
case CVTPT:
if (PSL & PSL_FPD) RSVD_INST_FAULT;
if ((op[0] > 31) || (op[3] > 31)) RSVD_OPND_FAULT;
if ((PSL & PSL_FPD) || (op[0] > 31) || (op[3] > 31))
RSVD_OPND_FAULT;
ReadDstr (op[0], op[1], &dst, acc); /* get source */
ProbeDstr (op[3], op[4], WA); /* test writeability */
for (i = 1; i <= op[3]; i++) { /* loop thru chars */
if (i != op[3]) { /* not last? */
if (i != 1) { /* not last? */
d = (dst.val[i / 8] >> ((i % 8) * 4)) & 0xF; /* get digit */
c = d + C_ZERO; /* convert */
}
else { /* translate last */
t = Read ((op[1] + op[0]) & LMASK, L_BYTE, RA);
t = Read ((op[1] + (op[0] / 2)) & LMASK, L_BYTE, RA);
c = Read ((op[2] + t) & LMASK, L_BYTE, RA);
}
Write ((op[4] + op[3] - i) & LMASK, c, L_BYTE, WA);
@ -971,8 +971,8 @@ case EDITPC:
}
else { /* new instr */
if (op[0] > 31) RSVD_OPND_FAULT; /* lnt > 31? */
d = Read ((op[1] + (op[0] / 2)) & LMASK, L_BYTE, RA) & 0xF;
if ((d == 0xB) || (d == 0xD)) {
t = Read ((op[1] + (op[0] / 2)) & LMASK, L_BYTE, RA) & 0xF;
if ((t == 0xB) || (t == 0xD)) {
cc = CC_N | CC_Z;
sign = C_MINUS;
}

View file

@ -81,6 +81,8 @@ int32 op_mulh (int32 *opnd, int32 *hf);
int32 op_divh (int32 *opnd, int32 *hf);
int32 op_emodh (int32 *opnd, int32 *hflt, int32 *intgr, int32 *flg);
void op_polyh (int32 *opnd, int32 acc);
void h_write_b (int32 spec, int32 va, int32 val, int32 acc);
void h_write_w (int32 spec, int32 va, int32 val, int32 acc);
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_o (int32 spec, int32 va, int32 *val, int32 acc);
@ -90,7 +92,6 @@ void vax_hmod (UFPH *a, int32 *intgr, int32 *flg);
void vax_hdiv (UFPH *a, UFPH *b);
void qp_add (UQP *a, UQP *b);
void qp_inc (UQP *a);
void qp_sub (UQP *a, UQP *b);
void qp_lsh (UQP *a, uint32 sc);
void qp_rsh (UQP *a, uint32 sc);
void qp_rsh_s (UQP *a, uint32 sc, uint32 neg);
@ -110,7 +111,7 @@ static int32 z_octa[4] = { 0, 0, 0, 0 };
int32 op_octa (int32 *opnd, int32 cc, int32 opc, int32 acc, int32 spec, int32 va)
{
int32 r, rh, temp, flg, rn;
int32 r, rh, temp, flg;
int32 r_octa[4];
switch (opc) {
@ -173,12 +174,14 @@ case MOVO:
h_write_o (spec, va, opnd, acc); /* write src */
CC_IIZP_O (opnd[0], opnd[1], opnd[2], opnd[3]); /* set cc's */
break;
case MOVH:
if (r = op_tsth (opnd[0])) /* test for 0 */
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 */
break;
case MNEGH:
if (r = op_tsth (opnd[0])) { /* test for 0 */
opnd[0] = opnd[0] ^ FPSIGN; /* nz, invert sign */
@ -211,11 +214,13 @@ case CVTBH:
h_write_o (spec, va, r_octa, acc); /* write reslt */
CC_IIZZ_FP (r); /* set cc's */
break;
case CVTWH:
r = op_cvtih (SXTW (opnd[0]), r_octa); /* convert */
h_write_o (spec, va, r_octa, acc); /* write result */
CC_IIZZ_FP (r); /* set cc's */
break;
case CVTLH:
r = op_cvtih (opnd[0], r_octa); /* convert */
h_write_o (spec, va, r_octa, acc); /* write result */
@ -232,22 +237,18 @@ case CVTLH:
case CVTHB:
r = op_cvthi (opnd, &temp, opc) & BMASK; /* convert */
if (spec > (GRN | nPC)) Write (va, r, L_BYTE, WA);
else {
rn = spec & 0xF;
R[rn] = (R[rn] & ~BMASK) | r; }
h_write_b (spec, va, r, acc); /* write result */
CC_IIZZ_B (r); /* set cc's */
cc = cc | temp; /* or in V */
break;
case CVTHW:
r = op_cvthi (opnd, &temp, opc) & WMASK; /* convert */
if (spec > (GRN | nPC)) Write (va, r, L_WORD, WA);
else {
rn = spec & 0xF;
R[rn] = (R[rn] & ~WMASK) | r; }
h_write_w (spec, va, r, acc); /* write result */
CC_IIZZ_W (r); /* set cc's */
cc = cc | temp; /* or in V */
break;
case CVTHL: case CVTRHL:
r = op_cvthi (opnd, &temp, opc) & LMASK; /* convert */
h_write_l (spec, va, r, acc); /* write result */
@ -282,6 +283,7 @@ case CVTDH:
h_write_o (spec, va, r_octa, acc); /* write result */
CC_IIZZ_FP (r); /* set cc's */
break;
case CVTGH:
r = op_cvtgh (opnd[0], opnd[1], r_octa); /* convert */
h_write_o (spec, va, r_octa, acc); /* write result */
@ -301,11 +303,13 @@ case CVTHF:
h_write_l (spec, va, r, acc); /* write result */
CC_IIZZ_FP (r); /* set cc's */
break;
case CVTHD:
r = op_cvthfd (opnd, &rh); /* convert */
h_write_q (spec, va, r, rh, acc); /* write result */
CC_IIZZ_FP (r); /* set cc's */
break;
case CVTHG:
r = op_cvthg (opnd, &rh); /* convert */
h_write_q (spec, va, r, rh, acc); /* write result */
@ -334,16 +338,19 @@ case ADDH2: case ADDH3:
h_write_o (spec, va, r_octa, acc); /* write result */
CC_IIZZ_FP (r); /* set cc's */
break;
case SUBH2: case SUBH3:
r = op_addh (opnd, r_octa, TRUE); /* subtract */
h_write_o (spec, va, r_octa, acc); /* write result */
CC_IIZZ_FP (r); /* set cc's */
break;
case MULH2: case MULH3:
r = op_mulh (opnd, r_octa); /* multiply */
h_write_o (spec, va, r_octa, acc); /* write result */
CC_IIZZ_FP (r); /* set cc's */
break;
case DIVH2: case DIVH3:
r = op_divh (opnd, r_octa); /* divide */
h_write_o (spec, va, r_octa, acc); /* write result */
@ -649,12 +656,9 @@ if ((a->exp < b->exp) || /* |s1| < |s2|? */
}
ediff = a->exp - b->exp; /* exp diff */
if (a->sign ^ b->sign) { /* eff sub? */
if (ediff) { /* exp diff? */
qp_neg (&b->frac); /* negate fraction */
qp_rsh_s (&b->frac, ediff, 1); /* signed right */
qp_add (&a->frac, &b->frac); /* "add" frac */
}
else qp_sub (&a->frac, &b->frac); /* a >= b */
qp_neg (&b->frac); /* negate fraction */
if (ediff) qp_rsh_s (&b->frac, ediff, 1); /* denormalize */
qp_add (&a->frac, &b->frac); /* "add" frac */
h_normh (a); /* normalize */
}
else { if (ediff) qp_rsh (&b->frac, ediff); /* add, denormalize */
@ -738,7 +742,7 @@ return;
void vax_hdiv (UFPH *a, UFPH *b)
{
int32 i;
UQP quo = { 0, 0, 0, 0 };
UQP ndvr, quo = { 0, 0, 0, 0 };
if (a->exp == 0) FLT_DZRO_FAULT; /* divr = 0? */
if (b->exp == 0) return; /* divd = 0? */
@ -746,11 +750,14 @@ b->sign = b->sign ^ a->sign; /* result sign */
b->exp = b->exp - a->exp + H_BIAS + 1; /* unbiased exp */
qp_rsh (&a->frac, 1); /* allow 1 bit left */
qp_rsh (&b->frac, 1);
ndvr = a->frac; /* copy divisor */
qp_neg (&ndvr); /* and negate */
for (i = 0; i < 128; i++) { /* divide loop */
qp_lsh (&quo, 1); /* shift quo */
if (qp_cmp (&b->frac, &a->frac) >= 0) { /* div step ok? */
qp_sub (&b->frac, &a->frac); /* subtract */
quo.f0 = quo.f0 + 1; } /* quo bit = 1 */
qp_add (&b->frac, &ndvr); /* "subtract" */
quo.f0 = quo.f0 + 1; /* quo bit = 1 */
}
qp_lsh (&b->frac, 1); /* shift divd */
}
b->frac = quo;
@ -803,15 +810,6 @@ r->f3 = (~r->f3 + (r->f2 == 0)) & LMASK;
return;
}
void qp_sub (UQP *a, UQP *b)
{
UQP nb = *b;
qp_neg (&nb);
qp_add (a, &nb);
return;
}
void qp_lsh (UQP *r, uint32 sc)
{
if (sc >= 128) r->f3 = r->f2 = r->f1 = r->f0 = 0; /* > 127? result 0 */
@ -1050,6 +1048,28 @@ hflt[3] = WORDSWAP (r->frac.f0);
return hflt[0];
}
void h_write_b (int32 spec, int32 va, int32 val, int32 acc)
{
int32 rn;
if (spec > (GRN | nPC)) Write (va, val, L_BYTE, WA);
else { rn = spec & 0xF;
R[rn] = (R[rn] & ~BMASK) | val;
}
return;
}
void h_write_w (int32 spec, int32 va, int32 val, int32 acc)
{
int32 rn;
if (spec > (GRN | nPC)) Write (va, val, L_WORD, WA);
else { rn = spec & 0xF;
R[rn] = (R[rn] & ~WMASK) | val;
}
return;
}
void h_write_l (int32 spec, int32 va, int32 val, int32 acc)
{
if (spec > (GRN | nPC)) Write (va, val, L_LONG, WA);
@ -1064,11 +1084,13 @@ int32 rn, mstat;
if (spec > (GRN | nPC)) {
if (Test (va + 7, WA, &mstat) >= 0)
Write (va, vl, L_LONG, WA);
Write (va + 4, vh, L_LONG, WA); }
Write (va + 4, vh, L_LONG, WA);
}
else { rn = spec & 0xF;
if (rn >= nSP) RSVD_ADDR_FAULT;
R[rn] = vl;
R[rn + 1] = vh; }
R[rn + 1] = vh;
}
return;
}
@ -1081,13 +1103,15 @@ if (spec > (GRN | nPC)) {
Write (va, val[0], L_LONG, WA);
Write (va + 4, val[1], L_LONG, WA);
Write (va + 8, val[2], L_LONG, WA);
Write (va + 12, val[3], L_LONG, WA); }
Write (va + 12, val[3], L_LONG, WA);
}
else { rn = spec & 0xF;
if (rn >= nAP) RSVD_ADDR_FAULT;
R[rn] = val[0];
R[rn + 1] = val[1];
R[rn + 2] = val[2];
R[rn + 3] = val[3]; }
R[rn + 3] = val[3];
}
return;
}

View file

@ -1,6 +1,6 @@
/* vax_sysdev.c: VAX 3900 system-specific logic
Copyright (c) 1998-2004, Robert M Supnik
Copyright (c) 1998-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"),
@ -32,6 +32,7 @@
cso console storage output
sysd system devices (SSC miscellany)
10-Mar-05 RMS Fixed bug in timer schedule routine (from Mark Hittinger)
30-Sep-04 RMS Moved CADR, MSER, CONPC, CONPSL, machine_check, cpu_boot,
con_halt here from vax_cpu.c
Moved model-specific IPR's here from vax_cpu1.c
@ -1283,7 +1284,7 @@ if (tmr_tir[tmr] > (0xFFFFFFFFu - TMR_INC)) { /* short interval? */
else { tmr_inc[tmr] = TMR_INC; /* usec/interval */
tmr_time = tmr_poll; }
if (tmr_time == 0) tmr_time = 1;
if ((tmr_inc[tmr] = TMR_INC) && (tmr_time > clk_time)) {
if ((tmr_inc[tmr] == TMR_INC) && (tmr_time > clk_time)) {
/* Align scheduled event to be identical to the event for the next clock
tick. This lets us always see a consistent calibrated value, both for

View file

@ -246,8 +246,14 @@ HP2100_SOURCE = $(HP2100_DIR)HP2100_STDDEV.C,$(HP2100_DIR)HP2100_DP.C,\
$(HP2100_DIR)HP2100_MT.C,$(HP2100_DIR)HP2100_MUX.C,\
$(HP2100_DIR)HP2100_CPU.C,$(HP2100_DIR)HP2100_FP.C,\
$(HP2100_DIR)HP2100_SYS.C,$(HP2100_DIR)HP2100_LPT.C,\
$(HP2100_DIR)HP2100_IPL.C,$(HP2100_DIR)HP2100_CPU1.C
$(HP2100_DIR)HP2100_IPL.C,$(HP2100_DIR)HP2100_CPU1.C,\
$(HP2100_DIR)HP2100_FP1.C
.IFDEF MMSALPHA
HP2100_OPTIONS = /INCLUDE=($(SIMH_DIR),$(HP2100_DIR))\
/DEFINE=($(CC_DEFS),"HAVE_INT64=1")
.ELSE
HP2100_OPTIONS = /INCLUDE=($(SIMH_DIR),$(HP2100_DIR))/DEFINE=($(CC_DEFS))
.ENDIF
#
# Interdata 16-bit CPU.

View file

@ -147,8 +147,9 @@ HP2100 = ${HP2100D}hp2100_stddev.c ${HP2100D}hp2100_dp.c ${HP2100D}hp2100_dq.c \
${HP2100D}hp2100_dr.c ${HP2100D}hp2100_lps.c ${HP2100D}hp2100_ms.c \
${HP2100D}hp2100_mt.c ${HP2100D}hp2100_mux.c ${HP2100D}hp2100_cpu.c \
${HP2100D}hp2100_fp.c ${HP2100D}hp2100_sys.c ${HP2100D}hp2100_lpt.c \
${HP2100D}hp2100_ipl.c ${HP2100D}hp2100_ds.c ${HP2100D}hp2100_cpu1.c
HP2100_OPT = -I ${HP2100D}
${HP2100D}hp2100_ipl.c ${HP2100D}hp2100_ds.c ${HP2100D}hp2100_cpu1.c \
${HP2100D}hp2100_fp1.c
HP2100_OPT = -DHAVE_INT64 -I ${HP2100D}

166
scp.c
View file

@ -23,6 +23,10 @@
be used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from Robert M Supnik.
01-May-05 RMS Revised syntax for SET DEBUG (from Dave Bryan)
22-Mar-05 JDB Modified DO command to allow ten-level nesting
18-Mar-05 RMS Moved DETACH tests into detach_unit (from Dave Bryan)
Revised interface to fprint_sym, fparse_sym
07-Feb-05 RMS Added ASSERT command (from Dave Bryan)
02-Feb-05 RMS Fixed bug in global register search
26-Dec-04 RMS Qualified SAVE examine, RESTORE deposit with SIM_SW_REST
@ -45,16 +49,14 @@
RMS Split out libraries
RMS Moved logging function to SCP
RMS Exposed step counter interface(s)
RMS Fixed double logging of SHOW BREAK
(found by Mark Pizzolato)
RMS Fixed double logging of SHOW BREAK (found by Mark Pizzolato)
RMS Fixed implementation of REG_VMIO
RMS Added SET/SHOW DEBUG, SET/SHOW <device> DEBUG,
SHOW <device> MODIFIERS, SHOW <device> RADIX
RMS Changed sim_fsize to take uptr argument
29-Dec-03 RMS Added Telnet console output stall support
01-Nov-03 RMS Cleaned up implicit detach on attach/restore
Fixed bug in command line read while logging
(found by Mark Pizzolato)
Fixed bug in command line read while logging (found by Mark Pizzolato)
01-Sep-03 RMS Fixed end-of-file problem in dep, idep
Fixed error on trailing spaces in dep, idep
15-Jul-03 RMS Removed unnecessary test in reset_all
@ -169,6 +171,7 @@
#define SSH_SH 1 /* show */
#define SSH_CL 2 /* clear */
#define DO_NEST_LVL 10 /* DO cmd nesting level */
#define SRBSIZ 1024 /* save/restore buffer */
#define SIM_BRK_INILNT 4096 /* bpt tbl length */
#define SIM_BRK_ALLTYP 0xFFFFFFFF
@ -388,7 +391,7 @@ const char *scp_error_messages[] = {
"Non-existent unit",
"Non-existent register",
"Non-existent parameter",
"Nested DO commands",
"Nested DO command limit exceeded",
"Internal error",
"Invalid magtape record length",
"Console Telnet connection lost",
@ -503,7 +506,7 @@ static CTAB cmd_table[] = {
"sh{ow} <dev} NAMES show device logical name\n"
"sh{ow} <dev> {arg,...} show device parameters\n"
"sh{ow} <unit> {arg,...} show unit parameters\n" },
{ "DO", &do_cmd, 0,
{ "DO", &do_cmd, 1,
"do <file> {arg,arg...} process command file\n" },
{ "ECHO", &echo_cmd, 0,
"echo <string> display <string>\n" },
@ -581,7 +584,7 @@ if (!sim_quiet) {
show_version (stdout, NULL, NULL, 0, NULL); }
if (*cbuf) { /* cmd file arg? */
stat = do_cmd (1, cbuf); /* proc cmd file */
stat = do_cmd (0, cbuf); /* proc cmd file */
if (stat == SCPE_OPENERR) /* error? */
fprintf (stderr, "Can't open file %s\n", cbuf); }
else if (*argv[0]) { /* sim name arg? */
@ -590,7 +593,7 @@ else if (*argv[0]) { /* sim name arg? */
strncpy (nbuf + 1, argv[0], PATH_MAX + 1); /* copy sim name */
if (np = match_ext (nbuf, "EXE")) *np = 0; /* remove .exe */
strcat (nbuf, ".ini\""); /* add .ini" */
stat = do_cmd (1, nbuf); } /* proc cmd file */
stat = do_cmd (0, nbuf); } /* proc cmd file */
while (stat != SCPE_EXIT) { /* in case exit */
printf ("sim> "); /* prompt */
@ -710,7 +713,8 @@ CTAB *cmdp;
int32 echo, nargs;
t_stat stat = SCPE_OK;
if (flag == 0) { GET_SWITCHES (fcptr); } /* get switches */
if (flag > 0) { GET_SWITCHES (fcptr); } /* get switches */
else flag = 1; /* start at level 1 */
echo = sim_switches & SWMASK ('V'); /* -v means echo */
c = fcptr;
@ -735,12 +739,13 @@ do { cptr = read_line (cbuf, CBUFSIZE, fpin); /* get cmd line */
if (echo && sim_log) fprintf (sim_log, "do> %s\n", cptr);
cptr = get_glyph (cptr, gbuf, 0); /* get command glyph */
sim_switches = 0; /* init switches */
if (strcmp (gbuf, "DO") == 0) { /* don't recurse */
fclose (fpin);
return SCPE_NEST; }
if (cmdp = find_cmd (gbuf)) /* lookup command */
stat = cmdp->action (cmdp->arg, cptr); /* if found, exec */
else stat = SCPE_UNK;
if (cmdp = find_cmd (gbuf)) { /* lookup command */
if (cmdp->action == &do_cmd) /* DO command? */
if (flag >= DO_NEST_LVL) /* nest too deep? */
stat = SCPE_NEST;
else stat = do_cmd (flag + 1, cptr); /* exec DO cmd */
else stat = cmdp->action (cmdp->arg, cptr); } /* exec other cmd */
else stat = SCPE_UNK; /* bad cmd given */
if (stat >= SCPE_BASE) { /* error? */
printf ("%s\n", scp_error_messages[stat - SCPE_BASE]);
if (sim_log) fprintf (sim_log, "%s\n",
@ -791,7 +796,7 @@ return;
t_stat assert_cmd (int32 flag, char *cptr)
{
char gbuf[CBUFSIZE], *gptr, *aptr;
char gbuf[CBUFSIZE], *gptr, *aptr, *tptr;
REG *rptr;
uint32 idx;
t_value val;
@ -805,13 +810,16 @@ rptr = find_reg (gbuf, &gptr, sim_dfdev); /* parse register */
if (!rptr) return SCPE_NXREG; /* not there */
if (*gptr == '[') { /* subscript? */
if (rptr->depth <= 1) return SCPE_ARG; /* array register? */
idx = (uint32) strtotv (++gptr, &cptr, 10); /* convert index */
if ((gptr == cptr) || (*cptr++ != ']')) return SCPE_ARG;
idx = (uint32) strtotv (++gptr, &tptr, 10); /* convert index */
if ((gptr == tptr) || (*tptr++ != ']')) return SCPE_ARG;
gptr = tptr; /* update */
}
else idx = 0; /* not array */
if (idx >= rptr->depth) return SCPE_SUB; /* validate subscript */
if (*cptr == 0) return SCPE_2FARG; /* must be more */
cptr = get_glyph (cptr, gbuf, 0); /* get search cond */
if (*gptr != 0) get_glyph (gptr, gbuf, 0); /* more? must be search */
else { if (*cptr == 0) return SCPE_2FARG; /* must be more */
cptr = get_glyph (cptr, gbuf, 0); /* get search cond */
}
if (*cptr != 0) return SCPE_2MARG; /* must be done */
if (!get_search (gbuf, rptr->radix, &sim_stab)) /* parse condition */
return SCPE_MISVAL;
@ -994,12 +1002,14 @@ DEBTAB *dep;
if ((dptr->flags & DEV_DEBUG) == 0) return SCPE_NOFNC;
if (cptr == NULL) { /* no arguments? */
if (dptr->debflags && flag) return SCPE_ARG; /* table or enable? */
dptr->dctrl = flag; /* no table or disable */
dptr->dctrl = flag; /* disable/enable w/o table */
if (flag && dptr->debflags) { /* enable with table? */
for (dep = dptr->debflags; dep->name != NULL; dep++)
dptr->dctrl = dptr->dctrl | dep->mask; } /* set all */
return SCPE_OK; }
if (dptr->debflags == NULL) return SCPE_ARG; /* must have table */
while (*cptr) {
cptr = get_glyph (cptr, gbuf, ','); /* get debug flag */
cptr = get_glyph (cptr, gbuf, ';'); /* get debug flag */
for (dep = dptr->debflags; dep->name != NULL; dep++) {
if (strcmp (dep->name, gbuf) == 0) { /* match? */
if (flag) dptr->dctrl = dptr->dctrl | dep->mask;
@ -1302,7 +1312,7 @@ if (dptr->flags & DEV_DEBUG) {
fputs ("Debug=", st);
for (dep = dptr->debflags; dep->name != NULL; dep++) {
if (dptr->dctrl & dep->mask) {
if (any) fputc (',', st);
if (any) fputc (';', st);
fputs (dep->name, st);
any = 1; }
}
@ -1400,7 +1410,7 @@ char gbuf[CBUFSIZE], *tptr, *t1ptr, *aptr;
DEVICE *dptr = sim_devices[0];
UNIT *uptr = dptr->units;
t_stat r;
t_addr lo, hi, max = uptr->capac - dptr->aincr;
t_addr lo, hi, max = uptr->capac - 1;
int32 cnt;
if (*cptr == 0) return SCPE_2FARG;
@ -1425,11 +1435,20 @@ while (*cptr) {
else if (flg == SSH_SH) sim_brk_showall (st, sim_switches);
else return SCPE_ARG; }
else {
for ( ; lo <= hi; lo = lo + dptr->aincr) {
if (flg == SSH_ST) r = sim_brk_set (lo, sim_switches, cnt, aptr);
else if (flg == SSH_CL) r = sim_brk_clr (lo, sim_switches);
else if (flg == SSH_SH) r = sim_brk_show (st, lo, sim_switches);
else return SCPE_ARG;
for ( ; lo <= hi; lo = lo + 1) {
switch (flg) {
case SSH_ST:
r = sim_brk_set (lo, sim_switches, cnt, aptr);
break;
case SSH_CL:
r = sim_brk_clr (lo, sim_switches);
break;
case SSH_SH:
r = sim_brk_show (st, lo, sim_switches);
break;
default:
return SCPE_ARG;
}
if (r != SCPE_OK) return r;
}
}
@ -1643,8 +1662,6 @@ if (strcmp (gbuf, "ALL") == 0) return (detach_all (0, FALSE));
dptr = find_unit (gbuf, &uptr); /* locate unit */
if (dptr == NULL) return SCPE_NXDEV; /* found dev? */
if (uptr == NULL) return SCPE_NXUN; /* valid unit? */
if (!(uptr->flags & UNIT_ATTABLE)) return SCPE_NOATT; /* attachable? */
if (!(uptr->flags & UNIT_ATT)) return SCPE_OK; /* attached? */
return scp_detach_unit (dptr, uptr); /* detach */
}
@ -1694,7 +1711,8 @@ t_stat detach_unit (UNIT *uptr)
DEVICE *dptr;
if (uptr == NULL) return SCPE_IERR;
if (!(uptr->flags & UNIT_ATT)) return SCPE_OK;
if (!(uptr->flags & UNIT_ATTABLE)) return SCPE_NOATT; /* attachable? */
if (!(uptr->flags & UNIT_ATT)) return SCPE_OK; /* attached? */
if ((dptr = find_dev_from_unit (uptr)) == NULL) return SCPE_OK;
if (uptr->flags & UNIT_BUF) {
uint32 cap = (uptr->hwmark + dptr->aincr - 1) / dptr->aincr;
@ -1710,7 +1728,8 @@ if (uptr->flags & UNIT_BUF) {
uptr->flags = uptr->flags & ~(UNIT_ATT | UNIT_RO);
free (uptr->filename);
uptr->filename = NULL;
return (fclose (uptr->fileref) == EOF)? SCPE_IOERR: SCPE_OK;
if (fclose (uptr->fileref) == EOF) return SCPE_IOERR;
return SCPE_OK;
}
/* Assign command
@ -1973,9 +1992,10 @@ for ( ;; ) { /* device loop */
uptr->flags = (uptr->flags & ~UNIT_RFLAGS) |
(flg & UNIT_RFLAGS); /* restore */
READ_S (buf); /* attached file */
if (!(dptr->flags & DEV_NET) || /* if not net dev or */
!(uptr->flags & UNIT_ATT) || /* not currently att */
(buf[0] == 0)) { /* or will not be att */
if ((uptr->flags & UNIT_ATTABLE) && /* if attachable and */
(!(dptr->flags & DEV_NET) || /* not net dev or */
!(uptr->flags & UNIT_ATT) || /* not currently att */
(buf[0] == 0))) { /* or will not be att */
sim_switches = SIM_SW_REST; /* att-det/rest */
r = scp_detach_unit (dptr, uptr); /* detach old */
if (r != SCPE_OK) return r;
@ -2328,20 +2348,26 @@ t_stat reason;
if (uptr->flags & UNIT_DIS) return SCPE_UDIS; /* disabled? */
mask = (t_addr) width_mask[dptr->awidth];
if ((low > mask) || (high > mask) || (low > high)) return SCPE_ARG;
for (i = low; i <= high; i = i + (dptr->aincr)) {
if ((flag & EX_E) || schptr) { /* examine or search? */
reason = get_aval (i, dptr, uptr); /* get data */
if (reason != SCPE_OK) return reason; /* return if error */
if (schptr && !test_search (sim_eval[0], schptr)) continue; }
if (flag != EX_D) {
reason = ex_addr (ofile, flag, i, dptr, uptr);
if (reason > SCPE_OK) return reason;
if (sim_log && (ofile == stdout))
ex_addr (sim_log, flag, i, dptr, uptr); }
if (flag != EX_E) {
reason = dep_addr (flag, cptr, i, dptr, uptr, reason);
if (reason > SCPE_OK) return reason; }
if (reason < SCPE_OK) i = i + ((-reason) * dptr->aincr); }
for (i = low; i <= high; ) { /* all paths must incr!! */
reason = get_aval (i, dptr, uptr); /* get data */
if (reason != SCPE_OK) return reason; /* return if error */
if (schptr && !test_search (sim_eval[0], schptr))
i = i + dptr->aincr; /* sch fails, incr */
else { /* no sch or success */
if (flag != EX_D) { /* ex, ie, or id? */
reason = ex_addr (ofile, flag, i, dptr, uptr);
if (reason > SCPE_OK) return reason;
if (sim_log && (ofile == stdout))
ex_addr (sim_log, flag, i, dptr, uptr);
}
else reason = 1 - dptr->aincr; /* no, dflt incr */
if (flag != EX_E) { /* ie, id, or d? */
reason = dep_addr (flag, cptr, i, dptr, uptr, reason);
if (reason > SCPE_OK) return reason;
}
i = i + (1 - reason); /* incr */
}
}
return SCPE_OK;
}
@ -2523,8 +2549,8 @@ return;
dptr = pointer to device
uptr = pointer to unit
Outputs:
return = if >= 0, error status
if < 0, number of extra words retired
return = if > 0, error status
if <= 0,-number of extra addr units retired
*/
t_stat ex_addr (FILE *ofile, int32 flag, t_addr addr, DEVICE *dptr, UNIT *uptr)
@ -2535,11 +2561,13 @@ int32 rdx;
if (sim_vm_fprint_addr) sim_vm_fprint_addr (ofile, dptr, addr);
else fprint_val (ofile, addr, dptr->aradix, dptr->awidth, PV_LEFT);
fprintf (ofile, ": ");
if (!(flag & EX_E)) return SCPE_OK;
if (!(flag & EX_E)) return (1 - dptr->aincr);
GET_RADIX (rdx, dptr->dradix);
if ((reason = fprint_sym (ofile, addr, sim_eval, uptr, sim_switches)) > 0)
reason = fprint_val (ofile, sim_eval[0], rdx, dptr->dwidth, PV_RZRO);
if ((reason = fprint_sym (ofile, addr, sim_eval, uptr, sim_switches)) > 0) {
fprint_val (ofile, sim_eval[0], rdx, dptr->dwidth, PV_RZRO);
reason = 1 - dptr->aincr;
}
if (flag & EX_I) fprintf (ofile, " ");
else fprintf (ofile, "\n");
return reason;
@ -2607,8 +2635,8 @@ return SCPE_OK;
uptr = pointer to unit
dfltinc = value to return on cr input
Outputs:
return = if >= 0, error status
if < 0, number of extra words retired
return = if > 0, error status
if <= 0, -number of extra address units retired
*/
t_stat dep_addr (int32 flag, char *cptr, t_addr addr, DEVICE *dptr,
@ -2624,8 +2652,8 @@ char gbuf[CBUFSIZE];
if (dptr == NULL) return SCPE_IERR;
if (flag & EX_I) {
cptr = read_line (gbuf, CBUFSIZE, stdin);
if (cptr == NULL) return 1; /* force exit */
if (sim_log) fprintf (sim_log, (cptr? "%s\n": "\n"), cptr);
if (cptr == NULL) return 1; /* force exit */
if (*cptr == 0) return dfltinc; } /* success */
if (uptr->flags & UNIT_RO) return SCPE_RO; /* read only? */
mask = width_mask[dptr->dwidth];
@ -2634,7 +2662,7 @@ GET_RADIX (rdx, dptr->dradix);
if ((reason = parse_sym (cptr, addr, uptr, sim_eval, sim_switches)) > 0) {
sim_eval[0] = get_uint (cptr, rdx, mask, &reason);
if (reason != SCPE_OK) return reason; }
count = 1 - reason;
count = (1 - reason + (dptr->aincr - 1)) / dptr->aincr;
for (i = 0, j = addr; i < count; i++, j = j + dptr->aincr) {
sim_eval[i] = sim_eval[i] & mask;
@ -2665,7 +2693,7 @@ return reason;
t_stat eval_cmd (int32 flg, char *cptr)
{
DEVICE *dptr = sim_devices[0];
int32 i, count, rdx;
int32 i, rdx, a, lim;
t_stat r;
GET_SWITCHES (cptr);
@ -2675,20 +2703,20 @@ if (*cptr == 0) return SCPE_2FARG;
if ((r = parse_sym (cptr, 0, dptr->units, sim_eval, sim_switches)) > 0) {
sim_eval[0] = get_uint (cptr, rdx, width_mask[dptr->dwidth], &r);
if (r != SCPE_OK) return r; }
count = 1 - r;
for (i = 0; count > 0; i++, count = count - dptr->aincr) {
printf ("%d:\t", i);
if ((r = fprint_sym (stdout, 0, &sim_eval[i], dptr->units, sim_switches)) > 0)
lim = 1 - r;
for (i = a = 0; a < lim; ) {
printf ("%d:\t", a);
if ((r = fprint_sym (stdout, a, &sim_eval[i], dptr->units, sim_switches)) > 0)
r = fprint_val (stdout, sim_eval[i], rdx, dptr->dwidth, PV_RZRO);
printf ("\n");
if (sim_log) {
fprintf (sim_log, "%d\t", i);
if ((r = fprint_sym (sim_log, 0, &sim_eval[i], dptr->units, sim_switches)) > 0)
if ((r = fprint_sym (sim_log, a, &sim_eval[i], dptr->units, sim_switches)) > 0)
r = fprint_val (sim_log, sim_eval[i], rdx, dptr->dwidth, PV_RZRO);
fprintf (sim_log, "\n"); }
if (r < 0) {
i = i - r;
count = count + (r * dptr->aincr); }
if (r < 0) a = a + 1 - r;
else a = a + dptr->aincr;
i = a / dptr->aincr;
}
return SCPE_OK;
}

View file

@ -23,6 +23,7 @@
be used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from Robert M Supnik.
11-Mar-05 RMS Moved 64b data type definitions outside USE_INT64
07-Feb-05 RMS Added assertion fail stop
05-Nov-04 RMS Added support for SHOW opt=val
20-Oct-04 RMS Converted all base types to typedefs
@ -115,8 +116,12 @@ typedef unsigned int uint32;
typedef int t_stat; /* status */
typedef int t_bool; /* boolean */
#if defined (USE_INT64) /* 64b data */
#if defined (_WIN32) /* Windows */
/* 64b integers */
#if defined (__GNUC__) /* GCC */
typedef signed long long t_int64;
typedef unsigned long long t_uint64;
#elif defined (_WIN32) /* Windows */
typedef signed __int64 t_int64;
typedef unsigned __int64 t_uint64;
#elif defined (__ALPHA) && defined (VMS) /* Alpha VMS */
@ -125,10 +130,12 @@ typedef unsigned __int64 t_uint64;
#elif defined (__ALPHA) && defined (__unix__) /* Alpha UNIX */
typedef signed long t_int64;
typedef unsigned long t_uint64;
#else /* default GCC */
typedef signed long long t_int64;
typedef unsigned long long t_uint64;
#endif /* end OS's */
#else /* default */
#define t_int64 signed long long
#define t_uint64 unsigned long long
#endif /* end 64b */
#if defined (USE_INT64) /* 64b data */
typedef t_int64 t_svalue; /* signed value */
typedef t_uint64 t_value; /* value */
#else /* 32b data */

View file

@ -28,13 +28,51 @@
#define _SIM_REV_H_ 0
#define SIM_MAJOR 3
#define SIM_MINOR 3
#define SIM_PATCH 2
#define SIM_MINOR 4
#define SIM_PATCH 0
/* V3.3 revision history
/* V3.4 revision history
patch date module(s) and fix(es)
0 01-May-04 scp.c:
- fixed ASSERT code
- revised syntax for SET DEBUG (from Dave Bryan)
- revised interpretation of fprint_sym, fparse_sym returns
- moved DETACH sanity tests into detach_unit
sim_sock.h and sim_sock.c:
- added test for WSAEINPROGRESS (from Tim Riker)
many: revised detach routines to test for attached state
hp2100_cpu.c: reorganized CPU options (from Dave Bryan)
hp2100_cpu1.c: reorganized EIG routines (from Dave Bryan)
hp2100_fp1.c: added FFP support (from Dave Bryan)
id16_cpu.c:
- fixed bug in show history routine (from Mark Hittinger)
- revised examine/deposit to do words rather than bytes
id32_cpu.c:
- fixed bug in initial memory allocation
- fixed bug in show history routine (from Mark Hittinger)
- revised examine/deposit to do words rather than bytes
id16_sys.c, id32_sys:
- revised examine/deposit to do words rather than bytes
pdp10_tu.c:
- fixed bug, ERASE and WREOF should not clear done (reported
by Rich Alderson)
- fixed error reporting
pdp11_tu.c: fixed error reporting
/* V3.3 revision history
2 08-Mar-05 scp.c: added ASSERT command (from Dave Bryan)
h316_defs.h: fixed IORETURN macro

View file

@ -1,6 +1,6 @@
/* sim_sock.c: OS-dependent socket routines
Copyright (c) 2001-2004, Robert M Supnik
Copyright (c) 2001-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"),
@ -23,6 +23,7 @@
be used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from Robert M Supnik.
14-Apr-05 RMS Added WSAEINPROGRESS test (from Tim Riker)
09-Jan-04 RMS Fixed typing problem in Alpha Unix (found by Tim Chapman)
17-Apr-03 RMS Fixed non-implemented version of sim_close_sock
(found by Mark Pizzolato)
@ -172,7 +173,9 @@ sta = sim_setnonblock (newsock); /* set nonblocking */
if (sta == SOCKET_ERROR) /* fcntl error? */
return sim_err_sock (newsock, "fcntl", 1);
sta = connect (newsock, (struct sockaddr *) &name, sizeof (name));
if ((sta == SOCKET_ERROR) && (WSAGetLastError () != WSAEWOULDBLOCK))
if ((sta == SOCKET_ERROR) &&
(WSAGetLastError () != WSAEWOULDBLOCK) &&
(WSAGetLastError () != WSAEINPROGRESS))
return sim_err_sock (newsock, "connect", 1);
return newsock; /* got it! */

View file

@ -1,6 +1,6 @@
/* sim_sock.h: OS-dependent socket routines header file
Copyright (c) 2001-2004, Robert M Supnik
Copyright (c) 2001-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"),
@ -23,6 +23,7 @@
be used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from Robert M Supnik.
14-Apr-05 RMS Added WSAEINPROGRESS (from Tim Riker)
20-Aug-04 HV Added missing definition for OS/2 (from Holger Veit)
22-Oct-03 MP Changed WIN32 winsock include to use winsock2.h to
avoid a conflict if sim_sock.h and sim_ether.h get
@ -49,6 +50,7 @@
#define WSAGetLastError() errno /* Windows macros */
#define SOCKET int32
#define WSAEWOULDBLOCK EWOULDBLOCK
#define WSAEINPROGRESS EINPROGRESS
#define INVALID_SOCKET -1
#define SOCKET_ERROR -1
#include <sys/types.h> /* for fcntl, getpid */

View file

@ -1,7 +1,7 @@
To: Users
From: Bob Supnik
Subj: Simulator Usage, V3.3
Date: 25-Jan-2005
Subj: Simulator Usage, V3.4
Date: 01-May-2005
COPYRIGHT NOTICE
@ -89,6 +89,13 @@ The simulators recognize or require a few compile-time #defines:
both USE_INT64 and USE_ADDR64 must be defined as part of the
compilation command line.
- The HP2100 Fast FORTRAN Processor (FFP) option requires 64b integer
support. Define HAVE_INT64 (not USE_INT64) as part of the compilation
command line if your host compiler supports 64b integers. On systems
without 64b support, the extended-precision instructions (e.g., XADD)
will be disabled; the remainder of the FFP instructions will work
normally. There may be some compilation warnings.
To start the simulator, simply type its name. (On version of VMS
prior to 6.2, the simulators must then be defined as foreign commands
in order to be be started by name.) The simulator recognizes one
@ -725,15 +732,60 @@ the next character is interpreted literally, even if it is % or \.
Arguments with spaces can be enclosed in matching single or double
quotation marks.
If the switch -V is specified, the commands in the file are echoed
before they are executed.
If the switch -V is specified, the commands in the file are echoed before
they are executed. DO commands may be nested up to ten invocations deep.
Several commands are particularly useful within command files. While they
may be executed interactively, they have only limited functionality when so
used.
3.13.1 Displaying Arbitrary Text
The ECHO command is a useful way of annotating command files. ECHO
prints out its argument on the console:
sim> ECHO <string> -- output string to console
If there is no argument, ECHO prints a blank line on the console. This may
be used to provide spacing in the console display or log.
If there is no argument, ECHO prints a blank line on the console.
3.13.2 Testing Simulator State
The ASSERT command tests a simulator state condition and halts command file
execution if the condition is false:
sim> ASSERT {<dev>} <reg>{<logical-op><value>}<conditional-op><value>
If <dev> is not specified, CPU is assumed. <reg> is a register (scalar or
subscripted) belonging to the indicated device. The <conditional-op> and
optional <logical-op> are the same as those used for "search specifiers" by
the EXAMINE and DEPOSIT commands (see above). The <value>s are expressed in
the radix specified for <reg>, not in the radix for the device.
If the <logical-op> and <value> are specified, the target register value is
first altered as indicated. The result is then compared to the <value> via
the <conditional-op>. If the result is false, an "Assertion failed" message
is printed, and any running command file is aborted. Otherwise, the command
has no effect.
For example, a command file might be used to bootstrap an operating system
that halts after the initial load from disk. The ASSERT command is then
used to confirm that the load completed successfully by examining the CPU's
"A" register for the expected value:
; OS bootstrap command file
;
ATTACH DS0 os.disk
BOOT DS
; A register contains error code; 0 = good boot
ASSERT A=0
ATTACH MT0 sys.tape
ATTACH MT1 user.tape
RUN
In the example, if the A register is not 0, the command file will be aborted
with an "Assertion failed (A=0)" message. Otherwise, the command file will
continue to bring up the operating system.
3.14 Executing System Commands
@ -768,13 +820,14 @@ or disabled entirely:
If debug output is enabled, individual devices can be controlled with the
SET command. If a device has only a single debug flag:
sim> SET <device> DEBUG -- enable device debug output
sim> SET <device> NODEBUG -- disable device debug output
sim> SET <device> DEBUG -- enable device debug output
sim> SET <device> NODEBUG -- disable device debug output
If the device has individual, named debug flags:
sim> SET <device> DEBUG=n1,n2,... -- enable device debug flags n1, n2, ...
sim> SET <device> NODEBUG=n1,n2,... -- disable device debug flags n1, n2, ...
sim> SET <device> DEBUG -- enable all device debug flags
sim> SET <device> DEBUG=n1;n2;... -- enable device debug flags n1, n2, ...
sim> SET <device> NODEBUG=n1;n2;... -- disable device debug flags n1, n2, ...
sim> SET <device> NODEBUG -- disable all device debug flags
If debug output is directed to stdout, it will be intermixed with normal
@ -957,6 +1010,9 @@ Revision History (covering Rev 2.0 to present)
Starting with Rev 2.7, detailed revision histories can be found
in file sim_rev.c.
Rev 3.4, May, 05
Revised memory interaction model
Rev 3.3, Nov, 04
Added PDP-11/VAX DHQ11 support
Added PDP-11/VAX TM02/TM03 support