761 lines
40 KiB
C
761 lines
40 KiB
C
/* hp2100_defs.h: HP 2100 System architectural declarations
|
|
|
|
Copyright (c) 1993-2016, Robert M. Supnik
|
|
Copyright (c) 2017 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 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.
|
|
|
|
10-Jan-17 JDB Added architectural constants
|
|
05-Aug-16 JDB Removed PC_Global renaming; P register is now "PR"
|
|
13-May-16 JDB Modified for revised SCP API function parameter types
|
|
19-Jun-15 JDB Conditionally use PC_Global for PC for version 4.0 and on
|
|
30-Dec-14 JDB Added S-register parameters to ibl_copy, more IBL constants
|
|
28-Dec-14 JDB Changed suppression from #pragma GCC to #pragma clang
|
|
05-Feb-13 JDB Added declaration for hp_fprint_stopped
|
|
18-Mar-13 JDB Added "-Wdangling-else" to the suppression pragmas
|
|
Removed redundant extern declarations
|
|
14-Mar-13 MP Changed guard macro name to avoid reserved namespace
|
|
14-Dec-12 JDB Added "-Wbitwise-op-parentheses" to the suppression pragmas
|
|
12-May-12 JDB Added pragmas to suppress logical operator precedence warnings
|
|
10-Feb-12 JDB Added hp_setsc, hp_showsc functions to support SC modifier
|
|
28-Mar-11 JDB Tidied up signal handling
|
|
29-Oct-10 JDB DMA channels renamed from 0,1 to 1,2 to match documentation
|
|
27-Oct-10 JDB Revised I/O signal enum values for concurrent signals
|
|
Revised I/O macros for new signal handling
|
|
09-Oct-10 JDB Added DA and DC device select code assignments
|
|
07-Sep-08 JDB Added POLL_FIRST to indicate immediate connection attempt
|
|
15-Jul-08 JDB Rearranged declarations with hp2100_cpu.h
|
|
26-Jun-08 JDB Rewrote device I/O to model backplane signals
|
|
25-Jun-08 JDB Added PIF device
|
|
17-Jun-08 JDB Declared fmt_char() function
|
|
26-May-08 JDB Added MPX device
|
|
24-Apr-08 JDB Added I_MRG_I, I_JSB, I_JSB_I, and I_JMP instruction masks
|
|
14-Apr-08 JDB Changed TMR_MUX to TMR_POLL for idle support
|
|
Added POLLMODE, sync_poll() declaration
|
|
Added I_MRG, I_ISZ, I_IOG, I_STF, and I_SFS instruction masks
|
|
07-Dec-07 JDB Added BACI device
|
|
10-Nov-07 JDB Added 16/32-bit unsigned-to-signed conversions
|
|
11-Jan-07 JDB Added 12578A DMA byte packing to DMA structure
|
|
28-Dec-06 JDB Added CRS backplane signal as I/O pseudo-opcode
|
|
Added DMASK32 32-bit mask value
|
|
21-Dec-06 JDB Changed MEM_ADDR_OK for 21xx loader support
|
|
12-Sep-06 JDB Define NOTE_IOG to recalc interrupts after instr exec
|
|
Rename STOP_INDINT to NOTE_INDINT (not a stop condition)
|
|
30-Dec-04 JDB Added IBL_DS_HEAD head number mask
|
|
19-Nov-04 JDB Added STOP_OFFLINE, STOP_PWROFF stop codes
|
|
25-Apr-04 RMS Added additional IBL definitions
|
|
Added DMA EDT I/O pseudo-opcode
|
|
25-Apr-03 RMS Revised for extended file support
|
|
24-Oct-02 RMS Added indirect address interrupt
|
|
08-Feb-02 RMS Added DMS definitions
|
|
01-Feb-02 RMS Added terminal multiplexor support
|
|
16-Jan-02 RMS Added additional device support
|
|
30-Nov-01 RMS Added extended SET/SHOW support
|
|
15-Oct-00 RMS Added dynamic device numbers
|
|
14-Apr-99 RMS Changed t_addr to unsigned
|
|
|
|
The [original] author gratefully acknowledges the help of Jeff Moffat in
|
|
answering questions about the HP2100; and of Dave Bryan in adding features
|
|
and correcting errors throughout the simulator.
|
|
|
|
|
|
This file provides the general declarations used throughout the HP 2100
|
|
simulator. It is required by all modules.
|
|
|
|
|
|
-----------------------------------------------------
|
|
Implementation Note -- Compiling the Simulator as C++
|
|
-----------------------------------------------------
|
|
|
|
Although simulators are written in C, the SIMH project encourages developers
|
|
to compile them with a C++ compiler to obtain the more careful type checking
|
|
provided. To obtain successful compilations, the simulator must be written
|
|
in the subset of C that is also valid C++. Using valid C features beyond
|
|
that subset, as the HP 2100 simulator does, will produce C++ compiler errors.
|
|
|
|
The standard C features used by the simulator that prevent error-free C++
|
|
compilation are:
|
|
|
|
1. Incomplete types.
|
|
|
|
In C, mutually recursive type definitions are allowed by the use of
|
|
incomplete type declarations, such as "DEVICE ms_dev;" followed later by
|
|
"DEVICE ms_dev {...};". Several HP device simulators use this feature to
|
|
place a pointer to the device structure in the "desc" field of an MTAB
|
|
array element, typically when the associated validation or display
|
|
routine handles multiple devices. As the DEVICE contains a pointer to
|
|
the MTAB array, and an MTAB array element contains a pointer to the
|
|
DEVICE, the definitions are mutually recursive, and incomplete types are
|
|
employed. C++ does not permit incomplete types.
|
|
|
|
2. Implicit conversion of ints to enums.
|
|
|
|
In C, enumeration types are compatible with integer types, and its
|
|
members are constants having type "int". As such, they are semantically
|
|
equivalent to and may be used interchangeably with integers. For the
|
|
developer, though, C enumerations have some advantages. In particular,
|
|
the compiler may check a "switch" statement to ensure that all of the
|
|
enumeration cases are covered. Also, a mathematical set may be modeled
|
|
by an enumeration type with disjoint enumerator values, with the bitwise
|
|
integer OR and AND operators modeling the set union and intersection
|
|
operations. The latter has direct support in the "gdb" debugger, which
|
|
will display an enumerated type value as a union of the various
|
|
enumerators. The HP simulator makes extensive use of both features to
|
|
model hardware signal buses (e.g., INBOUND_SET, OUTBOUND_SET) and so
|
|
performs bitwise integer operations on the enumerations to model signal
|
|
assertion and denial. In C++, implicit conversion from enumerations to
|
|
integers is allowed, but conversion from integers to enumerations is
|
|
illegal without explicit casts. Therefore, the idiom employed by the
|
|
simulator to assert a signal (e.g., "outbound_signals |= INTREQ") is
|
|
rejected by the C++ compiler.
|
|
|
|
3. Implicit increment operations on enums.
|
|
|
|
Because enums are compatible with integers in C, no special enumerator
|
|
increment operator is provided. To cycle through the range of an
|
|
enumeration type, e.g. in a "for" statement, the standard integer
|
|
increment operator, "++", is used. In C++, the "++" operator must be
|
|
overloaded with a version specific to the enumeration type; applying the
|
|
integer "++" to an enumeration is illegal.
|
|
|
|
4. Use of C++ keywords as variable names.
|
|
|
|
C++ reserves a number of additional keywords beyond those reserved by C.
|
|
Use of any of these keywords as a variable or type name is legal C but
|
|
illegal C++. The HP simulator uses variables named "class" and
|
|
"operator", which are keywords in C++.
|
|
|
|
The HP simulator is written in ISO standard C and will compile cleanly with a
|
|
compiler implementing the 1999 C standard. Compilation as C++ is not a goal
|
|
of the simulator and cannot work, given the incompatibilities listed above.
|
|
*/
|
|
|
|
|
|
#ifndef HP2100_DEFS_H_
|
|
#define HP2100_DEFS_H_ 0
|
|
|
|
|
|
#include "sim_rev.h"
|
|
#include "sim_defs.h"
|
|
|
|
|
|
|
|
/* The following pragmas quell clang and Microsoft Visual C++ warnings that are
|
|
on by default but should not be, in my opinion. They warn about the use of
|
|
perfectly valid code and require the addition of redundant parentheses and
|
|
braces to silence them. Rather than clutter up the code with scores of extra
|
|
symbols that, in my view, make the code harder to read and maintain, I elect
|
|
to suppress these warnings.
|
|
|
|
VC++ 2008 warning descriptions:
|
|
|
|
- 4114: "same type qualifier used more than once" [legal per C99]
|
|
|
|
- 4554: "check operator precedence for possible error; use parentheses to
|
|
clarify precedence"
|
|
|
|
- 4996: "function was declared deprecated"
|
|
*/
|
|
|
|
#if defined (__clang__)
|
|
#pragma clang diagnostic ignored "-Wlogical-op-parentheses"
|
|
#pragma clang diagnostic ignored "-Wbitwise-op-parentheses"
|
|
#pragma clang diagnostic ignored "-Wshift-op-parentheses"
|
|
#pragma clang diagnostic ignored "-Wdangling-else"
|
|
|
|
#elif defined (_MSC_VER)
|
|
#pragma warning (disable: 4114 4554 4996)
|
|
|
|
#endif
|
|
|
|
|
|
/* Simulator stop and notification codes */
|
|
|
|
#define STOP_RSRV 1 /* must be 1 */
|
|
#define STOP_IODV 2 /* must be 2 */
|
|
#define STOP_HALT 3 /* HALT */
|
|
#define STOP_IBKPT 4 /* breakpoint */
|
|
#define STOP_IND 5 /* indirect loop */
|
|
#define NOTE_INDINT 6 /* indirect intr */
|
|
#define STOP_NOCONN 7 /* no connection */
|
|
#define STOP_OFFLINE 8 /* device offline */
|
|
#define STOP_PWROFF 9 /* device powered off */
|
|
#define NOTE_IOG 10 /* I/O instr executed */
|
|
|
|
|
|
/* Modifier validation identifiers */
|
|
|
|
#define MTAB_XDV (MTAB_XTD | MTAB_VDV)
|
|
#define MTAB_XUN (MTAB_XTD | MTAB_VUN)
|
|
|
|
|
|
/* Architectural constants.
|
|
|
|
These macros specify the width, sign location, value mask, and minimum and
|
|
maximum signed and unsigned values for the data sizes supported by the
|
|
simulator. In addition, masks for 16-bit and 32-bit overflow are defined (an
|
|
overflow is indicated if the masked bits are not all ones or all zeros).
|
|
|
|
The HP_WORD type is used to declare variables that represent 16-bit registers
|
|
or buses in hardware.
|
|
*/
|
|
|
|
typedef uint16 HP_WORD; /* HP 16-bit data word representation */
|
|
|
|
#define R_MASK 0177777u /* 16-bit register mask */
|
|
|
|
#define D4_WIDTH 4 /* 4-bit data bit width */
|
|
#define D4_MASK 0017u /* 4-bit data mask */
|
|
|
|
#define D8_WIDTH 8 /* 8-bit data bit width */
|
|
#define D8_MASK 0377u /* 8-bit data mask */
|
|
#define D8_UMAX 0377u /* 8-bit unsigned maximum value */
|
|
#define D8_SMAX 0177u /* 8-bit signed maximum value */
|
|
#define D8_SMIN 0200u /* 8-bit signed minimum value */
|
|
#define D8_SIGN 0200u /* 8-bit sign */
|
|
|
|
#define D16_WIDTH 16 /* 16-bit data bit width */
|
|
#define D16_MASK 0177777u /* 16-bit data mask */
|
|
#define D16_UMAX 0177777u /* 16-bit unsigned maximum value */
|
|
#define D16_SMAX 0077777u /* 16-bit signed maximum value */
|
|
#define D16_SMIN 0100000u /* 16-bit signed minimum value */
|
|
#define D16_SIGN 0100000u /* 16-bit sign */
|
|
|
|
#define D32_WIDTH 32 /* 32-bit data bit width */
|
|
#define D32_MASK 037777777777u /* 32-bit data mask */
|
|
#define D32_UMAX 037777777777u /* 32-bit unsigned maximum value */
|
|
#define D32_SMAX 017777777777u /* 32-bit signed maximum value */
|
|
#define D32_SMIN 020000000000u /* 32-bit signed minimum value */
|
|
#define D32_SIGN 020000000000u /* 32-bit sign */
|
|
|
|
#define D48_WIDTH 48 /* 48-bit data bit width */
|
|
#define D48_MASK 07777777777777777uL /* 48-bit data mask */
|
|
#define D48_UMAX 07777777777777777uL /* 48-bit unsigned maximum value */
|
|
#define D48_SMAX 03777777777777777uL /* 48-bit signed maximum value */
|
|
#define D48_SMIN 04000000000000000uL /* 48-bit signed minimum value */
|
|
#define D48_SIGN 04000000000000000uL /* 48-bit sign */
|
|
|
|
#define D64_WIDTH 64 /* 64-bit data bit width */
|
|
#define D64_MASK 01777777777777777777777uL /* 64-bit data mask */
|
|
#define D64_UMAX 01777777777777777777777uL /* 64-bit unsigned maximum value */
|
|
#define D64_SMAX 00777777777777777777777uL /* 64-bit signed maximum value */
|
|
#define D64_SMIN 01000000000000000000000uL /* 64-bit signed minimum value */
|
|
#define D64_SIGN 01000000000000000000000uL /* 64-bit sign */
|
|
|
|
#define S16_OVFL_MASK ((uint32) D16_UMAX << D16_WIDTH | \
|
|
D16_SIGN) /* 16-bit signed overflow mask */
|
|
|
|
#define S32_OVFL_MASK ((t_uint64) D32_UMAX << D32_WIDTH | \
|
|
D32_SIGN) /* 32-bit signed overflow mask */
|
|
|
|
|
|
/* Memory constants */
|
|
|
|
#define OF_WIDTH 10 /* offset bit width */
|
|
#define OF_MASK ((1u << OF_WIDTH) - 1) /* offset mask (2 ** 10 - 1) */
|
|
#define OF_MAX ((1u << OF_WIDTH) - 1) /* offset maximum (2 ** 10 - 1) */
|
|
|
|
#define PG_WIDTH 10 /* page bit width */
|
|
#define PG_MASK ((1u << PG_WIDTH) - 1) /* page mask (2 ** 10 - 1) */
|
|
#define PG_MAX ((1u << PG_WIDTH) - 1) /* page maximum (2 ** 10 - 1) */
|
|
|
|
#define LA_WIDTH 15 /* logical address bit width */
|
|
#define LA_MASK ((1u << LA_WIDTH) - 1) /* logical address mask (2 ** 15 - 1) */
|
|
#define LA_MAX ((1u << LA_WIDTH) - 1) /* logical address maximum (2 ** 15 - 1) */
|
|
|
|
#define PA_WIDTH 20 /* physical address bit width */
|
|
#define PA_MASK ((1u << PA_WIDTH) - 1) /* physical address mask (2 ** 20 - 1) */
|
|
#define PA_MAX ((1u << PA_WIDTH) - 1) /* physical address maximum (2 ** 20 - 1) */
|
|
|
|
#define DV_WIDTH 16 /* data value bit width */
|
|
#define DV_MASK ((1u << DV_WIDTH) - 1) /* data value mask (2 ** 16 - 1) */
|
|
#define DV_SIGN ( 1u << (DV_WIDTH - 1)) /* data value sign (2 ** 15) */
|
|
#define DV_UMAX ((1u << DV_WIDTH) - 1) /* data value unsigned maximum (2 ** 16 - 1) */
|
|
#define DV_SMAX ((1u << (DV_WIDTH - 1)) - 1) /* data value signed maximum (2 ** 15 - 1) */
|
|
|
|
|
|
/* Portable conversions.
|
|
|
|
SIMH is written with the assumption that the defined-size types (e.g.,
|
|
uint16) are at least the required number of bits but may be larger.
|
|
Conversions that otherwise would make inherent size assumptions must instead
|
|
be coded explicitly. For example, doing:
|
|
|
|
negative_value_32 = (int32) negative_value_16;
|
|
|
|
...will not guarantee that bits 0-15 of "negative_value_32" are ones, whereas
|
|
the supplied sign-extension macro will.
|
|
|
|
The conversions available are:
|
|
|
|
- SEXT8 -- int8 sign-extended to int32
|
|
- SEXT16 -- int16 sign-extended to int32
|
|
- NEG16 -- int8 negated
|
|
- NEG16 -- int16 negated
|
|
- NEG32 -- int32 negated
|
|
- INT16 -- uint16 to int16
|
|
- INT32 -- uint32 to int32
|
|
|
|
|
|
Implementation notes:
|
|
|
|
1. The routines assume that 16-bit values are masked to exactly 16 bits
|
|
before invoking.
|
|
*/
|
|
|
|
#define SEXT8(x) (int32) ((x) & D8_SIGN ? (x) | ~D8_MASK : (x))
|
|
#define SEXT16(x) (int32) ((x) & D16_SIGN ? (x) | ~D16_MASK : (x))
|
|
|
|
#define NEG8(x) ((~(x) + 1) & D8_MASK)
|
|
#define NEG16(x) ((~(x) + 1) & D16_MASK)
|
|
#define NEG32(x) ((~(x) + 1) & D32_MASK)
|
|
|
|
#define INT16(u) ((u) > D16_SMAX ? (-(int16) (D16_UMAX - (u)) - 1) : (int16) (u))
|
|
#define INT32(u) ((u) > D32_SMAX ? (-(int32) (D32_UMAX - (u)) - 1) : (int32) (u))
|
|
|
|
|
|
/* Byte accessors.
|
|
|
|
These macros extract the upper and lower bytes from a word and form a word
|
|
from upper and lower bytes. Replacement of a byte within a word is also
|
|
provided, as is an enumeration type that defines byte selection.
|
|
|
|
The accessors are:
|
|
|
|
- UPPER_BYTE -- return the byte from the upper position of a word value
|
|
- LOWER_BYTE -- return the byte from the lower position of a word value
|
|
- TO_WORD -- return a word with the specified upper and lower bytes
|
|
|
|
- REPLACE_UPPER -- replace the upper byte of the word value
|
|
- REPLACE_LOWER -- replace the lower byte of the word value
|
|
|
|
*/
|
|
|
|
typedef enum {
|
|
upper, /* upper byte selected */
|
|
lower /* lower byte selected */
|
|
} BYTE_SELECTOR;
|
|
|
|
#define UPPER_BYTE(w) (uint8) ((w) >> D8_WIDTH & D8_MASK)
|
|
#define LOWER_BYTE(w) (uint8) ((w) & D8_MASK)
|
|
#define TO_WORD(u,l) (HP_WORD) (((u) & D8_MASK) << D8_WIDTH | (l) & D8_MASK)
|
|
|
|
#define REPLACE_UPPER(w,b) ((w) & D8_MASK | ((b) & D8_MASK) << D8_WIDTH)
|
|
#define REPLACE_LOWER(w,b) ((w) & D8_MASK << D8_WIDTH | (b) & D8_MASK)
|
|
|
|
|
|
/* Double-word accessors */
|
|
|
|
#define UPPER_WORD(d) (HP_WORD) ((d) >> D16_WIDTH & D16_MASK)
|
|
#define LOWER_WORD(d) (HP_WORD) ((d) & D16_MASK)
|
|
|
|
#define TO_DWORD(u,l) ((uint32) (u) << D16_WIDTH | (l))
|
|
|
|
|
|
/* Portable conversions (sign-extension, unsigned-to-signed) */
|
|
|
|
#define SEXT(x) ((int32) (((x) & SIGN)? ((x) | ~DMASK): ((x) & DMASK)))
|
|
|
|
|
|
/* Memory */
|
|
|
|
#define MEMSIZE (cpu_unit.capac) /* actual memory size */
|
|
#define VA_N_SIZE 15 /* virtual addr size */
|
|
#define VASIZE (1 << VA_N_SIZE)
|
|
#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 */
|
|
|
|
/* Architectural constants */
|
|
|
|
#define SIGN32 020000000000 /* 32b sign */
|
|
#define DMASK32 037777777777 /* 32b data mask/maximum value */
|
|
#define DMAX32 017777777777 /* 32b maximum signed value */
|
|
#define SIGN 0100000 /* 16b sign */
|
|
#define DMASK 0177777 /* 16b data mask/maximum value */
|
|
#define DMAX 0077777 /* 16b maximum signed value */
|
|
#define DMASK8 0377 /* 8b data mask/maximum value */
|
|
|
|
/* Timers */
|
|
|
|
#define TMR_CLK 0 /* clock */
|
|
#define TMR_POLL 1 /* input polling */
|
|
|
|
#define POLL_RATE 100 /* poll 100 times per second */
|
|
#define POLL_FIRST 1 /* first poll is "immediate" */
|
|
#define POLL_WAIT 15800 /* initial poll ~ 10 msec. */
|
|
|
|
typedef enum { INITIAL, SERVICE } POLLMODE; /* poll synchronization modes */
|
|
|
|
/* I/O instruction sub-opcodes */
|
|
|
|
#define soHLT 0 /* halt */
|
|
#define soFLG 1 /* set/clear flag */
|
|
#define soSFC 2 /* skip on flag clear */
|
|
#define soSFS 3 /* skip on flag set */
|
|
#define soMIX 4 /* merge into A/B */
|
|
#define soLIX 5 /* load into A/B */
|
|
#define soOTX 6 /* output from A/B */
|
|
#define soCTL 7 /* set/clear control */
|
|
|
|
/* I/O devices - fixed select code assignments */
|
|
|
|
#define CPU 000 /* interrupt control */
|
|
#define OVF 001 /* overflow */
|
|
#define DMALT1 002 /* DMA 1 alternate */
|
|
#define DMALT2 003 /* DMA 2 alternate */
|
|
#define PWR 004 /* power fail */
|
|
#define PRO 005 /* parity/mem protect */
|
|
#define DMA1 006 /* DMA channel 1 */
|
|
#define DMA2 007 /* DMA channel 2 */
|
|
|
|
/* I/O devices - variable select code assignment defaults */
|
|
|
|
#define PTR 010 /* 12597A-002 paper tape reader */
|
|
#define TTY 011 /* 12531C teleprinter */
|
|
#define PTP 012 /* 12597A-005 paper tape punch */
|
|
#define CLK 013 /* 12539C time-base generator */
|
|
#define LPS 014 /* 12653A line printer */
|
|
#define LPT 015 /* 12845A line printer */
|
|
#define MTD 020 /* 12559A data */
|
|
#define MTC 021 /* 12559A control */
|
|
#define DPD 022 /* 12557A data */
|
|
#define DPC 023 /* 12557A control */
|
|
#define DQD 024 /* 12565A data */
|
|
#define DQC 025 /* 12565A control */
|
|
#define DRD 026 /* 12610A data */
|
|
#define DRC 027 /* 12610A control */
|
|
#define MSD 030 /* 13181A data */
|
|
#define MSC 031 /* 13181A control */
|
|
#define IPLI 032 /* 12566B link in */
|
|
#define IPLO 033 /* 12566B link out */
|
|
#define DS 034 /* 13037A control */
|
|
#define BACI 035 /* 12966A Buffered Async Comm Interface */
|
|
#define MPX 036 /* 12792A/B/C 8-channel multiplexer */
|
|
#define PIF 037 /* 12620A/12936A Privileged Interrupt Fence */
|
|
#define MUXL 040 /* 12920A lower data */
|
|
#define MUXU 041 /* 12920A upper data */
|
|
#define MUXC 042 /* 12920A control */
|
|
#define DI_DA 043 /* 12821A Disc Interface with Amigo disc devices */
|
|
#define DI_DC 044 /* 12821A Disc Interface with CS/80 disc and tape devices */
|
|
|
|
#define OPTDEV 002 /* start of optional devices */
|
|
#define CRSDEV 006 /* start of devices that receive CRS */
|
|
#define VARDEV 010 /* start of variable assignments */
|
|
#define MAXDEV 077 /* end of select code range */
|
|
|
|
/* IBL assignments */
|
|
|
|
#define IBL_V_SEL 14 /* ROM select <15:14> */
|
|
#define IBL_M_SEL 03
|
|
#define IBL_PTR 0000000 /* ROM 0: 12992K paper tape reader (PTR) */
|
|
#define IBL_DP 0040000 /* ROM 1: 12992A 7900 disc (DP) */
|
|
#define IBL_DQ 0060000 /* ROM 1: 12992A 2883 disc (DQ) */
|
|
#define IBL_MS 0100000 /* ROM 2: 12992D 7970 tape (MS) */
|
|
#define IBL_DS 0140000 /* ROM 3: 12992B 7905/06/20/25 disc (DS) */
|
|
#define IBL_MAN 0010000 /* RPL/manual boot <13:12> */
|
|
#define IBL_V_DEV 6 /* select code <11:6> */
|
|
#define IBL_OPT 0000070 /* options in <5:3> */
|
|
#define IBL_DP_REM 0000001 /* DP removable <0:0> */
|
|
#define IBL_DS_HEAD 0000003 /* DS head number <1:0> */
|
|
#define IBL_LNT 64 /* boot ROM length in words */
|
|
#define IBL_MASK (IBL_LNT - 1) /* boot length mask */
|
|
#define IBL_DPC (IBL_LNT - 2) /* DMA ctrl word */
|
|
#define IBL_END (IBL_LNT - 1) /* last location */
|
|
|
|
#define IBL_S_CLR 0000000 /* ibl_copy mask to clear the S register */
|
|
#define IBL_S_NOCLR 0177777 /* ibl_copy mask to preserve the S register */
|
|
#define IBL_S_NOSET 0000000 /* ibl_copy mask to preserve the S register */
|
|
|
|
#define IBL_SET_SC(s) ((s) << IBL_V_DEV) /* position the select code in the S register */
|
|
|
|
typedef uint16 BOOT_ROM [IBL_LNT]; /* boot ROM data */
|
|
|
|
|
|
/* I/O backplane signals.
|
|
|
|
The IOSIGNAL declarations mirror the hardware I/O backplane signals. A set
|
|
of one or more signals forms an IOCYCLE that is sent to a device IOHANDLER
|
|
for action. The CPU and DMA dispatch one signal set to the target device
|
|
handler per I/O cycle. A CPU cycle consists of either one or two signals; if
|
|
present, the second signal will be CLF. A DMA cycle consists of from two to
|
|
five signals. In addition, a front-panel PRESET or power-on reset dispatches
|
|
two or three signals, respectively.
|
|
|
|
In hardware, signals are assigned to one or more specific I/O T-periods, and
|
|
some signals are asserted concurrently. For example, a programmed STC sc,C
|
|
instruction asserts the STC and CLF signals together in period T4. Under
|
|
simulation, signals are ORed to form an I/O cycle; in this example, the
|
|
signal handler would receive an IOCYCLE value of "ioSTC | ioCLF".
|
|
|
|
Hardware allows parallel action for concurrent signals. Under simulation, a
|
|
"concurrent" set of signals is processed sequentially by the signal handler
|
|
in order of ascending numerical value. Although assigned T-periods differ
|
|
between programmed I/O and DMA I/O cycles, a single processing order is used.
|
|
The order of execution generally follows the order of T-period assertion,
|
|
except that ioSIR is processed after all other signals that may affect the
|
|
interrupt request chain.
|
|
|
|
Implementation notes:
|
|
|
|
1. The ioCLF signal must be processed after ioSFS/ioSFC to ensure that a
|
|
true skip test generates ioSKF before the flag is cleared, and after
|
|
ioIOI/ioIOO/ioSTC/ioCLC to meet the requirement that executing an
|
|
instruction having the H/C bit set is equivalent to executing the same
|
|
instruction with the H/C bit clear and then a CLF instruction.
|
|
|
|
2. The ioSKF signal is never sent to an I/O handler. Rather, it is returned
|
|
from the handler if the SFC or SFS condition is true. If the condition
|
|
is false, ioNONE is returned instead. As these two values are returned
|
|
in the 16-bit data portion of the returned value, their assigned values
|
|
must be <= 100000 octal.
|
|
|
|
3. An I/O handler will receive ioCRS as a result of a CLC 0 instruction,
|
|
ioPOPIO and ioCRS as a result of a RESET command, and ioPON, ioPOPIO, and
|
|
ioCRS as a result of a RESET -P command.
|
|
|
|
4. An I/O handler will receive ioNONE when a HLT instruction is executed
|
|
that has the H/C bit clear (i.e., no CLF generated).
|
|
|
|
5. In hardware, the SIR signal is generated unconditionally every T5 period
|
|
to time the setting of the IRQ flip-flop. Under simulation, ioSIR
|
|
indicates that the I/O handler must set the PRL, IRQ, and SRQ signals as
|
|
required by the interface logic. ioSIR must be included in the I/O cycle
|
|
if any of the flip-flops affecting these signals are changed and the
|
|
interface supports interrupts or DMA transfers.
|
|
|
|
6. In hardware, the ENF signal is unconditionally generated every T2 period
|
|
to time the setting of the flag flip-flop and to reset the IRQ flip-flop.
|
|
If the flag buffer flip-flip is set, then flag will be set by ENF. If
|
|
the flag buffer is clear, ENF will not affect flag. Under simulation,
|
|
ioENF is sent to set the flag buffer and flag flip-flops. For those
|
|
interfaces where this action is identical to that provided by STF, the
|
|
ioENF handler may simply fall into the ioSTF handler.
|
|
|
|
7. In hardware, the PON signal is asserted continuously while the CPU is
|
|
operating. Under simulation, ioPON is asserted only at simulator
|
|
initialization or when processing a RESET -P command.
|
|
*/
|
|
|
|
typedef enum { ioNONE = 0000000, /* -- -- -- -- -- no signal asserted */
|
|
ioPON = 0000001, /* T2 T3 T4 T5 T6 power on normal */
|
|
ioENF = 0000002, /* T2 -- -- -- -- enable flag */
|
|
ioIOI = 0000004, /* -- -- T4 T5 -- I/O data input (CPU)
|
|
T2 T3 -- -- -- I/O data input (DMA) */
|
|
ioIOO = 0000010, /* -- T3 T4 -- -- I/O data output */
|
|
ioSKF = 0000020, /* -- T3 T4 T5 -- skip on flag */
|
|
ioSFS = 0000040, /* -- T3 T4 T5 -- skip if flag is set */
|
|
ioSFC = 0000100, /* -- T3 T4 T5 -- skip if flag is clear */
|
|
ioSTC = 0000200, /* -- -- T4 -- -- set control flip-flop (CPU)
|
|
-- T3 -- -- -- set control flip-flop (DMA) */
|
|
ioCLC = 0000400, /* -- -- T4 -- -- clear control flip-flop (CPU)
|
|
-- T3 T4 -- -- clear control flip-flop (DMA) */
|
|
ioSTF = 0001000, /* -- T3 -- -- -- set flag flip-flop */
|
|
ioCLF = 0002000, /* -- -- T4 -- -- clear flag flip-flop (CPU)
|
|
-- T3 -- -- -- clear flag flip-flop (DMA) */
|
|
ioEDT = 0004000, /* -- -- T4 -- -- end data transfer */
|
|
ioCRS = 0010000, /* -- -- -- T5 -- control reset */
|
|
ioPOPIO = 0020000, /* -- -- -- T5 -- power-on preset to I/O */
|
|
ioIAK = 0040000, /* -- -- -- -- T6 interrupt acknowledge */
|
|
ioSIR = 0100000 } IOSIGNAL; /* -- -- -- T5 -- set interrupt request */
|
|
|
|
|
|
typedef uint32 IOCYCLE; /* a set of signals forming one I/O cycle */
|
|
|
|
#define IOIRQSET (ioSTC | ioCLC | ioENF | \
|
|
ioSTF | ioCLF | ioIAK | \
|
|
ioCRS | ioPOPIO | ioPON) /* signals that may affect interrupt state */
|
|
|
|
|
|
/* Flip-flops */
|
|
|
|
typedef enum {
|
|
CLEAR = 0, /* the flip-flop is clear */
|
|
SET = 1 /* the flip-flop is set */
|
|
} FLIP_FLOP;
|
|
|
|
#define TOGGLE(ff) ff = (FLIP_FLOP) (ff ^ 1) /* toggle a flip-flop variable */
|
|
|
|
#define D_FF(b) (FLIP_FLOP) ((b) != 0) /* use a Boolean expression for a D flip-flop */
|
|
|
|
|
|
/* I/O structures */
|
|
|
|
typedef struct dib DIB; /* incomplete definition */
|
|
|
|
typedef uint32 IOHANDLER (DIB *dibptr, /* I/O signal handler prototype */
|
|
IOCYCLE signal_set,
|
|
uint32 stat_data);
|
|
|
|
struct dib { /* Device information block */
|
|
IOHANDLER *io_handler; /* pointer to device's I/O signal handler */
|
|
uint32 select_code; /* device's select code */
|
|
uint32 card_index; /* device's card index for state variables */
|
|
};
|
|
|
|
|
|
/* I/O signal and status macros.
|
|
|
|
The following macros are useful in I/O signal handlers and unit service
|
|
routines. The parameter definition symbols employed are:
|
|
|
|
I = an IOCYCLE value
|
|
E = a t_stat error status value
|
|
D = a uint16 data value
|
|
C = a uint32 combined status and data value
|
|
P = a pointer to a DIB structure
|
|
B = a Boolean test value
|
|
|
|
Implementation notes:
|
|
|
|
1. The IONEXT macro isolates the next signal in sequence to process from the
|
|
I/O cycle I.
|
|
|
|
2. The IOADDSIR macro adds an ioSIR signal to the I/O cycle I if it
|
|
contains signals that might change the interrupt state.
|
|
|
|
3. The IORETURN macro forms the combined status and data value to be
|
|
returned by a handler from the t_stat error code E and the 16-bit data
|
|
value D.
|
|
|
|
4. The IOSTATUS macro isolates the t_stat error code from a combined status
|
|
and data value value C.
|
|
|
|
5. The IODATA macro isolates the 16-bit data value from a combined status
|
|
and data value value C.
|
|
|
|
6. The IOPOWERON macro calls signal handler P->H with DIB pointer P to
|
|
process a power-on reset action.
|
|
|
|
7. The IOPRESET macro calls signal handler P->H with DIB pointer P to
|
|
process a front-panel PRESET action.
|
|
|
|
8. The IOERROR macro returns t_stat error code E from a unit service routine
|
|
if the Boolean test B is true.
|
|
*/
|
|
|
|
#define IONEXT(I) (IOSIGNAL) ((I) & (IOCYCLE) (- (int32) (I))) /* extract next I/O signal to handle */
|
|
#define IOADDSIR(I) ((I) & IOIRQSET ? (I) | ioSIR : (I)) /* add SIR if IRQ state might change */
|
|
|
|
#define IORETURN(E,D) ((uint32) ((E) << 16 | (D) & DMASK)) /* form I/O handler return value */
|
|
#define IOSTATUS(C) ((t_stat) ((C) >> 16) & DMASK) /* extract I/O status from combined value */
|
|
#define IODATA(C) ((uint16) ((C) & DMASK)) /* extract data from combined value */
|
|
|
|
#define IOPOWERON(P) (P)->io_handler ((P), ioPON | ioPOPIO | ioCRS, 0) /* send power-on signals to handler */
|
|
#define IOPRESET(P) (P)->io_handler ((P), ioPOPIO | ioCRS, 0) /* send PRESET signals to handler */
|
|
#define IOERROR(B,E) ((B) ? (E) : SCPE_OK) /* stop on I/O error if enabled */
|
|
|
|
|
|
/* I/O signal logic macros.
|
|
|
|
The following macros implement the logic for the SKF, PRL, IRQ, and SRQ
|
|
signals. Both standard and general logic macros are provided. The parameter
|
|
definition symbols employed are:
|
|
|
|
S = a uint32 select code value
|
|
B = a Boolean test value
|
|
N = a name of a structure containing the standard flip-flops
|
|
|
|
Implementation notes:
|
|
|
|
1. The setSKF macro sets the Skip on Flag signal in the return data value if
|
|
the Boolean value B is true.
|
|
|
|
2. The setPRL macro sets the Priority Low signal for select code S to the
|
|
Boolean value B.
|
|
|
|
3. The setIRQ macro sets the Interrupt Request signal for select code S to
|
|
the Boolean value B.
|
|
|
|
4. The setSRQ macro sets the Service Request signal for select code S to the
|
|
Boolean value B.
|
|
|
|
5. The PRL macro returns the Priority Low signal for select code S as a
|
|
Boolean value.
|
|
|
|
6. The IRQ macro returns the Interrupt Request signal for select code S as a
|
|
Boolean value.
|
|
|
|
7. The SRQ macro returns the Service Request signal for select code S as a
|
|
Boolean value.
|
|
|
|
8. The setstdSKF macro sets Skip on Flag signal in the return data value if
|
|
the flag state in structure N matches the current skip test condition.
|
|
|
|
9. The setstdPRL macro sets the Priority Low signal for the select code
|
|
referenced by "dibptr" using the standard logic and the control and flag
|
|
states in structure N.
|
|
|
|
10. The setstdIRQ macro sets the Interrupt Request signal for the select code
|
|
referenced by "dibptr" using the standard logic and the control, flag,
|
|
and flag buffer states in structure N.
|
|
|
|
11. The setstdSRQ macro sets the Service Request signal for the select code
|
|
referenced by "dibptr" using the standard logic and the flag state in
|
|
structure N.
|
|
*/
|
|
|
|
#define BIT_V(S) ((S) & 037) /* convert select code to bit position */
|
|
#define BIT_M(S) (1u << BIT_V (S)) /* convert select code to bit mask */
|
|
|
|
#define setSKF(B) stat_data = IORETURN (SCPE_OK, (uint16) ((B) ? ioSKF : ioNONE))
|
|
|
|
#define setPRL(S,B) dev_prl[(S)/32] = dev_prl[(S)/32] & ~BIT_M (S) | (((B) & 1) << BIT_V (S))
|
|
#define setIRQ(S,B) dev_irq[(S)/32] = dev_irq[(S)/32] & ~BIT_M (S) | (((B) & 1) << BIT_V (S))
|
|
#define setSRQ(S,B) dev_srq[(S)/32] = dev_srq[(S)/32] & ~BIT_M (S) | (((B) & 1) << BIT_V (S))
|
|
|
|
#define PRL(S) ((dev_prl[(S)/32] >> BIT_V (S)) & 1)
|
|
#define IRQ(S) ((dev_irq[(S)/32] >> BIT_V (S)) & 1)
|
|
#define SRQ(S) ((dev_srq[(S)/32] >> BIT_V (S)) & 1)
|
|
|
|
#define setstdSKF(N) setSKF ((signal == ioSFC) && !N.flag || \
|
|
(signal == ioSFS) && N.flag)
|
|
|
|
#define setstdPRL(N) setPRL (dibptr->select_code, !(N.control & N.flag));
|
|
#define setstdIRQ(N) setIRQ (dibptr->select_code, N.control & N.flag & N.flagbuf);
|
|
#define setstdSRQ(N) setSRQ (dibptr->select_code, N.flag);
|
|
|
|
|
|
/* CPU state */
|
|
|
|
extern uint32 dev_prl [2], dev_irq [2], dev_srq [2]; /* I/O signal vectors */
|
|
|
|
/* CPU functions */
|
|
|
|
extern t_stat ibl_copy (const BOOT_ROM rom, int32 dev, uint32 sr_clear, uint32 sr_set);
|
|
extern void hp_enbdis_pair (DEVICE *ccp, DEVICE *dcp);
|
|
|
|
/* System functions */
|
|
|
|
extern const char *fmt_char (uint8 ch);
|
|
extern t_stat hp_setsc (UNIT *uptr, int32 val, CONST char *cptr, void *desc);
|
|
extern t_stat hp_setdev (UNIT *uptr, int32 val, CONST char *cptr, void *desc);
|
|
extern t_stat hp_showsc (FILE *st, UNIT *uptr, int32 val, CONST void *desc);
|
|
extern t_stat hp_showdev (FILE *st, UNIT *uptr, int32 val, CONST void *desc);
|
|
extern t_bool hp_fprint_stopped (FILE *st, t_stat reason);
|
|
|
|
/* Device-specific functions */
|
|
|
|
extern int32 sync_poll (POLLMODE poll_mode);
|
|
|
|
#endif
|