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:
parent
098200a126
commit
ec60bbf329
62 changed files with 4332 additions and 7632 deletions
|
@ -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
38
0readme_34.txt
Normal 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
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 */
|
||||
}
|
||||
|
|
|
@ -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 == ' ') {
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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"),
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
2550
HP2100/hp2100_cpu1.c
2550
HP2100/hp2100_cpu1.c
File diff suppressed because it is too large
Load diff
|
@ -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 */
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
508
HP2100/hp2100_fp1.c
Normal 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
52
HP2100/hp2100_fp1.h
Normal 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
|
|
@ -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)
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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? */
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
1079
VAX/vax780_doc.txt
1079
VAX/vax780_doc.txt
File diff suppressed because it is too large
Load diff
696
VAX/vax780_mba.c
696
VAX/vax780_mba.c
|
@ -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;
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
1104
VAX/vax780_uba.c
1104
VAX/vax780_uba.c
File diff suppressed because it is too large
Load diff
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
5
makefile
5
makefile
|
@ -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
166
scp.c
|
@ -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;
|
||||
}
|
||||
|
|
19
sim_defs.h
19
sim_defs.h
|
@ -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 */
|
||||
|
|
44
sim_rev.h
44
sim_rev.h
|
@ -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
|
||||
|
|
|
@ -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! */
|
||||
|
|
|
@ -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 */
|
||||
|
|
76
simh_doc.txt
76
simh_doc.txt
|
@ -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
|
||||
|
|
Loading…
Add table
Reference in a new issue