1
0
mirror of https://github.com/simh/simh.git synced 2026-01-11 23:52:58 +00:00

HP2100: HP 2100 release 26

See HP2100/hp2100_release.txt for details of the release
This commit is contained in:
Mark Pizzolato 2017-05-01 15:47:33 -07:00
parent af54a5c8fd
commit 90e9c2f4a0
13 changed files with 780 additions and 262 deletions

View File

@ -1,6 +1,9 @@
HP 2100 SIMULATOR FIXES
=======================
Last update: 2016-08-05
HP 2100 SIMULATOR FIX ARCHIVE
=============================
Final update: 2016-08-05
See the "SIMH/HP 2100 Release Notes" file for bug fixes implemented after the
date above.
1. PROBLEM: Booting from magnetic tape reports "HALT instruction, P: 77756

View File

@ -1,30 +1,33 @@
/* hp2100_cpu1.c: HP 2100/1000 EAU simulator and UIG dispatcher
Copyright (c) 2005-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:
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.
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHOR 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
Except as contained in this notice, the names of the authors 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.
in this Software without prior written authorization from the authors.
CPU1 Extended arithmetic and optional microcode dispatchers
22-Apr-17 JDB Improved the EAU shift/rotate instructions
21-Mar-17 JDB Fixed UIG 1 comment regarding 2000 IOP and F-Series
05-Aug-16 JDB Renamed the P register from "PC" to "PR"
24-Dec-14 JDB Added casts for explicit downward conversions
05-Apr-14 JDB Corrected typo in comments for cpu_ops
@ -172,173 +175,249 @@
EXECUTE (100120), is also described but was never implemented, and the
E/F-series microcode execute a NOP for this instruction code.
Notes:
1. Under simulation, TIMER, DIAG, and EXECUTE cause undefined instruction
stops if the CPU is set to 21xx. DIAG and EXECUTE also cause stops on
the 1000-M. TIMER does not, because it is used by several HP programs
to differentiate between M- and E/F-series machines.
Implementation notes:
2. DIAG is not implemented under simulation. On the E/F, it performs a
destructive test of all installed memory. Because of this, it is only
functional if the machine is halted, i.e., if the instruction is
executed with the INSTR STEP button. If it is executed in a program,
the result is NOP.
1. Under simulation, TIMER, DIAG, and EXECUTE cause undefined instruction
stops if the CPU is set to 21xx. DIAG and EXECUTE also cause stops on
the 1000-M. TIMER does not, because it is used by several HP programs
to differentiate between M- and E/F-series machines.
3. RRR is permitted and executed as NOP if the CPU is a 2114, as the
presence of the EAU is tested by the diagnostic configurator to
differentiate between 2114 and 2100/1000 CPUs.
2. DIAG is not implemented under simulation. On the E/F, it performs a
destructive test of all installed memory. Because of this, it is only
functional if the machine is halted, i.e., if the instruction is
executed with the INSTR STEP button. If it is executed in a program,
the result is NOP.
3. RRR is permitted and executed as NOP if the CPU is a 2114, as the
presence of the EAU is tested by the diagnostic configurator to
differentiate between 2114 and 2100/1000 CPUs.
4. The shift count is calculated unconditionally, as six of the ten
instructions will be using the value.
5. An arithmetic left shift must be handled as a special case because the
shifted operand bits "skip over" the sign bit. That is, the bits are
lost from the next-most-significant bit while preserving the MSB. For
all other shifts, including the arithmetic right shift, the operand may
be shifted and then merged with the appropriate fill bits.
6. The C standard specifies that the results of bitwise shifts with negative
signed operands are undefined (for left shifts) or implementation-defined
(for right shifts). Therefore, we must use unsigned operands and handle
arithmetic shifts explicitly.
*/
t_stat cpu_eau (uint32 IR, uint32 intrq)
{
t_stat reason = SCPE_OK;
OPS op;
uint32 rs, qs, sc, v1, v2, t;
uint32 rs, qs, v1, v2, operand, fill, mask, shift;
int32 sop1, sop2;
if ((cpu_unit.flags & UNIT_EAU) == 0) /* option installed? */
if ((UNIT_CPU_MODEL == UNIT_2114) && (IR == 0101100)) /* 2114 and RRR 16? */
if (UNIT_CPU_MODEL == UNIT_2114 && IR == 0101100) /* 2114 and RRR 16? */
return SCPE_OK; /* allowed as NOP */
else
return stop_inst; /* fail */
if (IR & 017) /* if the shift count is 1-15 */
shift = IR & 017; /* then use it verbatim */
else /* otherwise the count iz zero */
shift = 16; /* so use a shift count of 16 */
switch ((IR >> 8) & 0377) { /* decode IR<15:8> */
case 0200: /* EAU group 0 */
switch ((IR >> 4) & 017) { /* decode IR<7:4> */
case 000: /* DIAG 100000 */
if ((UNIT_CPU_MODEL != UNIT_1000_E) && /* must be 1000 E-series */
(UNIT_CPU_MODEL != UNIT_1000_F)) /* or 1000 F-series */
return stop_inst; /* trap if not */
break; /* DIAG is NOP unless halted */
case 000: /* DIAG 100000 */
if ((UNIT_CPU_MODEL != UNIT_1000_E) && /* must be 1000 E-series */
(UNIT_CPU_MODEL != UNIT_1000_F)) /* or 1000 F-series */
return stop_inst; /* trap if not */
break; /* DIAG is NOP unless halted */
case 001: /* ASL 100020-100037 */
sc = (IR & 017)? (IR & 017): 16; /* get sc */
O = 0; /* clear ovflo */
while (sc-- != 0) { /* bit by bit */
t = BR << 1; /* shift B */
BR = (BR & SIGN) | (t & 077777) | (AR >> 15);
AR = (AR << 1) & DMASK;
if ((BR ^ t) & SIGN) O = 1;
}
break;
case 002: /* LSL 100040-100057 */
sc = (IR & 017)? (IR & 017): 16; /* get sc */
BR = ((BR << sc) | (AR >> (16 - sc))) & DMASK;
AR = (AR << sc) & DMASK; /* BR'AR lsh left */
break;
case 001: /* ASL 100020-100037 */
operand = TO_DWORD (BR, AR); /* form the double-word operand */
case 003: /* TIMER 100060 */
if (UNIT_CPU_TYPE != UNIT_TYPE_1000) /* must be 1000 */
return stop_inst; /* trap if not */
if (UNIT_CPU_MODEL == UNIT_1000_M) /* 1000 M-series? */
goto MPY; /* decode as MPY */
BR = (BR + 1) & DMASK; /* increment B */
if (BR) PR = err_PC; /* if !=0, repeat */
break;
mask = D32_UMAX << 31 - shift; /* form a mask for the bits that will be lost */
case 004: /* RRL 100100-100117 */
sc = (IR & 017)? (IR & 017): 16; /* get sc */
t = BR; /* BR'AR rot left */
BR = ((BR << sc) | (AR >> (16 - sc))) & DMASK;
AR = ((AR << sc) | (t >> (16 - sc))) & DMASK;
break;
if (operand & D32_SIGN) /* if the operand is negative */
O = (~operand & mask & D32_MASK) != 0; /* then set overflow if any of the lost bits are zeros */
else /* otherwise it's positive */
O = (operand & mask & D32_MASK) != 0; /* so set overflow if any of the lost bits are ones */
case 010: /* MPY 100200 (OP_K) */
MPY:
reason = cpu_ops (OP_K, op, intrq); /* get operand */
if (reason == SCPE_OK) { /* successful eval? */
sop1 = SEXT (AR); /* sext AR */
sop2 = SEXT (op[0].word); /* sext mem */
sop1 = sop1 * sop2; /* signed mpy */
BR = (sop1 >> 16) & DMASK; /* to BR'AR */
AR = sop1 & DMASK;
O = 0; /* no overflow */
}
break;
operand = operand << shift & D32_SMAX /* shift the operand left */
| operand & D32_SIGN; /* while keeping the original sign bit */
default: /* others undefined */
return stop_inst;
BR = UPPER_WORD (operand); /* split the operand */
AR = LOWER_WORD (operand); /* into its constituent parts */
break;
case 002: /* LSL 100040-100057 */
operand = TO_DWORD (BR, AR) << shift; /* shift the double-word operand left */
BR = UPPER_WORD (operand); /* split the operand */
AR = LOWER_WORD (operand); /* into its constituent parts */
break;
case 004: /* RRL 100100-100117 */
operand = TO_DWORD (BR, AR); /* form the double-word operand */
fill = operand; /* and fill with operand bits */
operand = operand << shift /* rotate the operand left */
| fill >> 32 - shift; /* while filling in on the right */
BR = UPPER_WORD (operand); /* split the operand */
AR = LOWER_WORD (operand); /* into its constituent parts */
break;
case 003: /* TIMER 100060 */
if (UNIT_CPU_TYPE != UNIT_TYPE_1000) /* must be 1000 */
return stop_inst; /* trap if not */
if (UNIT_CPU_MODEL != UNIT_1000_M) { /* 1000 E/F-series? */
BR = (BR + 1) & DMASK; /* increment B */
if (BR) /* if !=0, repeat */
PR = err_PC;
break;
}
/* fall into the MPY case if 1000 M-Series */
case 010: /* MPY 100200 (OP_K) */
reason = cpu_ops (OP_K, op, intrq); /* get operand */
if (reason == SCPE_OK) { /* successful eval? */
sop1 = SEXT (AR); /* sext AR */
sop2 = SEXT (op[0].word); /* sext mem */
sop1 = sop1 * sop2; /* signed mpy */
BR = UPPER_WORD (sop1); /* to BR'AR */
AR = LOWER_WORD (sop1);
O = 0; /* no overflow */
}
break;
default: /* others undefined */
return stop_inst;
}
break;
case 0201: /* DIV 100400 (OP_K) */
reason = cpu_ops (OP_K, op, intrq); /* get operand */
if (reason != SCPE_OK) /* eval failed? */
break;
rs = qs = BR & SIGN; /* save divd sign */
if (rs) { /* neg? */
AR = (~AR + 1) & DMASK; /* make B'A pos */
BR = (~BR + (AR == 0)) & DMASK; /* make divd pos */
}
v2 = op[0].word; /* divr = mem */
if (v2 & SIGN) { /* neg? */
v2 = (~v2 + 1) & DMASK; /* make divr pos */
qs = qs ^ SIGN; /* sign of quotient */
}
if (BR >= v2) O = 1; /* divide work? */
if (BR >= v2) /* if the divisor is too small */
O = 1; /* then set overflow */
else { /* maybe... */
O = 0; /* assume ok */
v1 = (BR << 16) | AR; /* 32b divd */
AR = (v1 / v2) & DMASK; /* quotient */
BR = (v1 % v2) & DMASK; /* remainder */
if (AR) { /* quotient > 0? */
if (qs) AR = (~AR + 1) & DMASK; /* apply quo sign */
if ((AR ^ qs) & SIGN) O = 1; /* still wrong? ovflo */
if (qs) /* apply quo sign */
AR = NEG16 (AR);
if ((AR ^ qs) & SIGN) /* still wrong? ovflo */
O = 1;
}
if (rs) BR = (~BR + 1) & DMASK; /* apply rem sign */
if (rs)
BR = NEG16 (BR); /* apply rem sign */
}
break;
case 0202: /* EAU group 2 */
switch ((IR >> 4) & 017) { /* decode IR<7:4> */
case 001: /* ASR 101020-101037 */
sc = (IR & 017)? (IR & 017): 16; /* get sc */
AR = ((BR << (16 - sc)) | (AR >> sc)) & DMASK;
BR = (SEXT (BR) >> sc) & DMASK; /* BR'AR ash right */
O = 0;
break;
case 001: /* ASR 101020-101037 */
O = 0; /* clear ovflo */
case 002: /* LSR 101040-101057 */
sc = (IR & 017)? (IR & 017): 16; /* get sc */
AR = ((BR << (16 - sc)) | (AR >> sc)) & DMASK;
BR = BR >> sc; /* BR'AR log right */
break;
operand = TO_DWORD (BR, AR); /* form the double-word operand */
fill = (operand & D32_SIGN ? ~0 : 0); /* and fill with copies of the sign bit */
case 004: /* RRR 101100-101117 */
sc = (IR & 017)? (IR & 017): 16; /* get sc */
t = AR; /* BR'AR rot right */
AR = ((AR >> sc) | (BR << (16 - sc))) & DMASK;
BR = ((BR >> sc) | (t << (16 - sc))) & DMASK;
break;
operand = operand >> shift /* shift the operand right */
| fill << 32 - shift; /* while filling in with sign bits */
default: /* others undefined */
return stop_inst;
BR = UPPER_WORD (operand); /* split the operand */
AR = LOWER_WORD (operand); /* into its constituent parts */
break;
case 002: /* LSR 101040-101057 */
operand = TO_DWORD (BR, AR) >> shift; /* shift the double-word operand right */
BR = UPPER_WORD (operand); /* split the operand */
AR = LOWER_WORD (operand); /* into its constituent parts */
break;
case 004: /* RRR 101100-101117 */
operand = TO_DWORD (BR, AR); /* form the double-word operand */
fill = operand; /* and fill with operand bits */
operand = operand >> shift /* rotate the operand right */
| fill << 32 - shift; /* while filling in on the left */
BR = UPPER_WORD (operand); /* split the operand */
AR = LOWER_WORD (operand); /* into its constituent parts */
break;
default: /* others undefined */
return stop_inst;
}
break;
case 0210: /* DLD 104200 (OP_D) */
reason = cpu_ops (OP_D, op, intrq); /* get operand */
if (reason == SCPE_OK) { /* successful eval? */
AR = (op[0].dword >> 16) & DMASK; /* load AR */
BR = op[0].dword & DMASK; /* load BR */
AR = UPPER_WORD (op[0].dword); /* load AR */
BR = LOWER_WORD (op[0].dword); /* load BR */
}
break;
case 0211: /* DST 104400 (OP_A) */
reason = cpu_ops (OP_A, op, intrq); /* get operand */
if (reason == SCPE_OK) { /* successful eval? */
WriteW (op[0].word, AR); /* store AR */
WriteW ((op[0].word + 1) & VAMASK, BR); /* store BR */
}
break;
default: /* should never get here */
return SCPE_IERR; /* bad call from cpu_instr */
}
@ -521,8 +600,8 @@ return cpu_user (IR, intrq); /* try user microcode */
Instructions Option Name 1000-M 1000-E 1000-F
------------- ---------------------------- ------ ------ ------
10x400-10x437 2000 IOP opt opt opt
10x460-10x477 2000 IOP opt opt opt
10x400-10x437 2000 IOP opt opt -
10x460-10x477 2000 IOP opt opt -
10x460-10x477 Vector Instruction Set - - opt
10x520-10x537 Distributed System opt - -
10x600-10x617 SIGNAL/1000 Instruction Set - - opt

View File

@ -1,6 +1,7 @@
/* hp2100_defs.h: HP 2100 simulator definitions
/* 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"),
@ -23,6 +24,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.
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
@ -71,9 +73,80 @@
15-Oct-00 RMS Added dynamic device numbers
14-Apr-99 RMS Changed t_addr to unsigned
The 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.
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.
*/
@ -86,18 +159,32 @@
/* The following pragmas quell clang 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.
/* 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 "-Wdangling-else"
#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
@ -114,6 +201,181 @@
#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 */
@ -134,13 +396,6 @@
#define DMAX 0077777 /* 16b maximum signed value */
#define DMASK8 0377 /* 8b data mask/maximum value */
/* Portable conversions (sign-extension, unsigned-to-signed) */
#define SEXT(x) ((int32) (((x) & SIGN)? ((x) | ~DMASK): ((x) & DMASK)))
#define INT16(u) ((u) > DMAX ? (-(int16) (DMASK - (u)) - 1) : (int16) (u))
#define INT32(u) ((u) > DMAX32 ? (-(int32) (DMASK32 - (u)) - 1) : (int32) (u))
/* Timers */
#define TMR_CLK 0 /* clock */
@ -332,9 +587,19 @@ typedef uint32 IOCYCLE; /* a set of signals form
ioCRS | ioPOPIO | ioPON) /* signals that may affect interrupt state */
/* I/O structures */
/* Flip-flops */
typedef enum { CLEAR, SET } FLIP_FLOP; /* flip-flop type and values */
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 */

View File

@ -1,6 +1,6 @@
/* hp2100_di.c: HP 12821A HP-IB Disc Interface simulator
Copyright (c) 2010-2016, J. David Bryan
Copyright (c) 2010-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"),
@ -25,6 +25,7 @@
DI 12821A Disc Interface
17-Jan-17 JDB Changed to use new byte accessors in hp2100_defs.h
13-May-16 JDB Modified for revised SCP API function parameter types
24-Dec-14 JDB Added casts for explicit downward conversions
Removed redundant global declarations
@ -33,10 +34,10 @@
09-Oct-10 JDB Created DI simulation
References:
- HP 12821A Disc Interface Installation and Service Manual (12821-90006,
Feb-1985)
- IEEE Standard Digital Interface for Programmable Instrumentation
(IEEE-488A-1980, Sep-1979)
- HP 12821A Disc Interface Installation and Service Manual
(12821-90006, February 1985)
- IEEE Standard Digital Interface for Programmable Instrumentation
(IEEE-488A-1980, September 1979)
The 12821A was a high-speed implementation of the Hewlett-Packard Interface
@ -1609,7 +1610,7 @@ if (di_card->cntl_register & CNTL_LSTN) { /* is the card receiving
if ((di_card->cntl_register & CNTL_EOI /* EOI detection is enabled, */
&& di_card->bus_cntl & BUS_EOI) /* and data was tagged with EOI? */
|| (di_card->cntl_register & CNTL_LF /* or LF detection is enabled, */
&& GET_LOWER (data) == LF)) { /* and the byte is a line feed? */
&& LOWER_BYTE (data) == LF)) { /* and the byte is a line feed? */
tag = tag | TAG_LBR; /* tag as the last byte received */
di_card->status_register |= STAT_LBI; /* set the last byte in status */
}
@ -1633,10 +1634,10 @@ if (access == bus_access) { /* is this a bus access
if (tag & TAG_LBR) /* is this the last byte? */
di_card->fifo [index] = /* copy to both bytes of the FIFO */
tag | SET_BOTH (data); /* and store with the tag */
tag | TO_WORD (data, data); /* and store with the tag */
else { /* more bytes are expected */
di_card->fifo [index] = /* so position this byte */
tag | SET_UPPER (data); /* and store it with the tag */
tag | TO_WORD (data, 0); /* and store it with the tag */
add_word = FALSE; /* wait for the second byte before adding */
}
}
@ -1646,18 +1647,18 @@ if (access == bus_access) { /* is this a bus access
di_card->ibp = upper; /* set the upper byte as next */
di_card->fifo [index] = /* merge the data and tag values */
tag | di_card->fifo [index] | SET_LOWER (data);
tag | di_card->fifo [index] | TO_WORD (0, data);
}
else /* the card is in unpacked mode */
di_card->fifo [index] = /* position this byte */
tag | SET_LOWER (data); /* and store with the tag */
tag | TO_WORD (0, data); /* and store with the tag */
}
else if (access == cpu_access) /* is this a cpu access? */
di_card->fifo [index] = tag | data; /* store the tag and full word in the FIFO */
else { /* must be diagnostic access */
data = SET_BOTH (GET_LOWER (data)); /* copy the lower byte to the upper byte */
data = TO_WORD (data, data); /* copy the lower byte to the upper byte */
di_card->fifo [index] = tag | data; /* and store the tag and full word in the FIFO */
}
@ -1814,19 +1815,19 @@ if (access == cpu_access) { /* is this a cpu access?
else if (access == bus_access) /* is this a bus access? */
if (di_card->obp == upper) { /* is this the upper byte? */
di_card->obp = lower; /* set the lower byte as next */
data = GET_UPPER (data); /* mask and position the upper byte in the data word */
data = UPPER_BYTE (data); /* mask and position the upper byte in the data word */
remove_word = FALSE; /* do not unload the FIFO until the next byte */
}
else { /* this is the lower byte */
data = GET_LOWER (data); /* mask and position it in the data word */
data = LOWER_BYTE (data); /* mask and position it in the data word */
if (di_card->cntl_register & CNTL_PACK) /* is the card in the packed mode? */
di_card->obp = upper; /* set the upper byte as next */
}
else /* must be a diagnostic access */
data = GET_LOWER (data); /* access is to the lower byte only */
data = LOWER_BYTE (data); /* access is to the lower byte only */
if (remove_word) { /* remove the word from the FIFO? */

View File

@ -1,6 +1,6 @@
/* hp2100_di.h: HP 12821A HP-IB Disc Interface simulator definitions
/* hp2100_di.h: HP 12821A HP-IB Disc Interface simulator declarations
Copyright (c) 2010-2016, J. David Bryan
Copyright (c) 2010-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"),
@ -25,6 +25,7 @@
DI 12821A Disc Interface
10-Jan-17 JDB Moved byte accessors to hp2100_defs.h
13-May-16 JDB Modified for revised SCP API function parameter types
14-Feb-12 JDB First release
16-Nov-10 JDB Created DI common definitions file
@ -136,36 +137,17 @@ typedef enum {
#define PPR(a) (uint8) (1 << (7 - (a))) /* parallel poll response */
/* Byte accessors */
#define BYTE_SHIFT 8 /* byte shift count */
#define UPPER_BYTE 0177400 /* high-order byte mask */
#define LOWER_BYTE 0000377 /* low-order byte mask */
#define GET_UPPER(w) (uint8) (((w) & UPPER_BYTE) >> BYTE_SHIFT)
#define GET_LOWER(w) (uint8) ((w) & LOWER_BYTE)
#define SET_UPPER(b) (uint16) ((b) << BYTE_SHIFT)
#define SET_LOWER(b) (uint16) (b)
#define SET_BOTH(b) (SET_UPPER (b) | SET_LOWER (b))
typedef enum {
upper, /* upper byte selected */
lower /* lower byte selected */
} SELECTOR;
/* Per-card state variables */
typedef struct {
FLIP_FLOP control; /* control flip-flop */
FLIP_FLOP flag; /* flag flip-flop */
FLIP_FLOP flagbuf; /* flag buffer flip-flop */
FLIP_FLOP srq; /* SRQ flip-flop */
FLIP_FLOP edt; /* EDT flip-flop */
FLIP_FLOP eor; /* EOR flip-flop */
SELECTOR ibp; /* input byte pointer selector */
SELECTOR obp; /* output byte pointer selector */
FLIP_FLOP control; /* control flip-flop */
FLIP_FLOP flag; /* flag flip-flop */
FLIP_FLOP flagbuf; /* flag buffer flip-flop */
FLIP_FLOP srq; /* SRQ flip-flop */
FLIP_FLOP edt; /* EDT flip-flop */
FLIP_FLOP eor; /* EOR flip-flop */
BYTE_SELECTOR ibp; /* input byte pointer selector */
BYTE_SELECTOR obp; /* output byte pointer selector */
uint16 cntl_register; /* control word register */
uint16 status_register; /* status word register */

View File

@ -1,6 +1,6 @@
/* hp2100_di_da.c: HP 12821A HP-IB Disc Interface simulator for Amigo disc drives
Copyright (c) 2011-2016, J. David Bryan
Copyright (c) 2011-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"),
@ -25,6 +25,7 @@
DA 12821A Disc Interface with Amigo disc drives
17-Jan-17 JDB Changed to use new byte accessors in hp2100_defs.h
13-May-16 JDB Modified for revised SCP API function parameter types
04-Mar-16 JDB Name changed to "hp2100_disclib" until HP 3000 integration
30-Dec-14 JDB Added S-register parameters to ibl_copy
@ -36,16 +37,20 @@
04-Nov-11 JDB Created DA device
References:
- HP 13365 Integrated Controller Programming Guide (13365-90901, Feb-1980)
- HP 7910 Disc Drive Service Manual (07910-90903, Apr-1981)
- 12745D Disc Controller (13037) to HP-IB Adapter Kit Installation and
Service Manual (12745-90911, Sep-1983)
- HP's 5 1/4-Inch Winchester Disc Drive Service Documentation
(09134-90032, Aug-1983)
- HP 12992 Loader ROMs Installation Manual (12992-90001, Apr-1986)
- RTE Driver DVA32 Source (92084-18708, revision 2540)
- IEEE Standard Digital Interface for Programmable Instrumentation
(IEEE-488A-1980, Sep-1979)
- HP 13365 Integrated Controller Programming Guide
(13365-90901, February 1980)
- HP 7910 Disc Drive Service Manual
(07910-90903, April 1981)
- 12745D Disc Controller (13037) to HP-IB Adapter Kit Installation and Service Manual
(12745-90911, September 1983)
- HP's 5 1/4-Inch Winchester Disc Drive Service Documentation
(09134-90032, August 1983)
- HP 12992 Loader ROMs Installation Manual
(12992-90001, April 1986)
- RTE Driver DVA32 Source
(92084-18708, revision 2540)
- IEEE Standard Digital Interface for Programmable Instrumentation
(IEEE-488A-1980, September 1979)
The HP 7906H, 7920H, and 7925H Integrated Controller Disc (ICD) drives were
@ -1713,7 +1718,7 @@ else { /* it is bus data (A
if (DEBUG_PRI (da_dev, DEB_XFER))
sprintf (action, "opcode %02XH", data & DL_OPCODE_MASK);
buffer [0] = SET_UPPER (data); /* set the opcode into the buffer */
buffer [0] = TO_WORD (data, 0); /* set the opcode into the buffer */
if (dl_prepare_command (&icd_cntlr [unit], /* is the command valid? */
da_unit, unit)) {
@ -2081,9 +2086,9 @@ static uint8 get_buffer_byte (CVPTR cvptr)
cvptr->length = cvptr->length - 1; /* count the byte */
if (cvptr->length & 1) /* is the upper byte next? */
return GET_UPPER (buffer [cvptr->index]); /* return the byte */
return UPPER_BYTE (buffer [cvptr->index]); /* return the byte */
else /* the lower byte is next */
return GET_LOWER (buffer [cvptr->index++]); /* return the byte and bump the word index */
return LOWER_BYTE (buffer [cvptr->index++]); /* return the byte and bump the word index */
}
@ -2103,9 +2108,9 @@ static void put_buffer_byte (CVPTR cvptr, uint8 data)
cvptr->length = cvptr->length - 1; /* count the byte */
if (cvptr->length & 1) /* is the upper byte next? */
buffer [cvptr->index] = SET_UPPER (data); /* save the byte */
buffer [cvptr->index] = TO_WORD (data, 0); /* save the byte */
else /* the lower byte is next */
buffer [cvptr->index++] |= SET_LOWER (data); /* merge the byte and bump the word index */
buffer [cvptr->index++] |= TO_WORD (0, data); /* merge the byte and bump the word index */
return;
}

View File

@ -1,6 +1,6 @@
/* hp2100_disclib.c: HP MAC/ICD disc controller simulator library
Copyright (c) 2011-2016, J. David Bryan
Copyright (c) 2011-2017, J. David Bryan
Copyright (c) 2004-2011, Robert M. Supnik
Permission is hereby granted, free of charge, to any person obtaining a
@ -24,6 +24,9 @@
used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from the authors.
22-Apr-17 JDB A failed sim_fseek call now causes a drive fault
09-Mar-17 JDB Added the simulator name to the "perror" message.
17-Jan-17 JDB Moved "hp2100_defs.h" inclusion to "hp2100_disclib.c"
13-May-16 JDB Modified for revised SCP API function parameter types
04-Mar-16 JDB Name changed to "hp2100_disclib" until HP 3000 integration
24-Dec-14 JDB Added casts for explicit downward conversions
@ -256,6 +259,7 @@
#include <math.h>
#include "hp2100_defs.h" /* this must reflect the machine used */
#include "hp2100_disclib.h"
@ -552,7 +556,7 @@ static void start_write (CVPTR cvptr, UNIT *uptr);
static t_stat end_write (CVPTR cvptr, UNIT *uptr);
static t_bool position_sector (CVPTR cvptr, UNIT *uptr, t_bool verify);
static void next_sector (CVPTR cvptr, UNIT *uptr);
static t_stat io_error (CVPTR cvptr, UNIT *uptr);
static t_stat io_error (CVPTR cvptr, UNIT *uptr, CNTLR_STATUS status);
/* Disc library local utility routines */
@ -1808,8 +1812,8 @@ count = sim_fread (cvptr->buffer + offset, /* read the sector from
for (count = count + offset; count < cvptr->length; count++) /* pad the sector as needed */
cvptr->buffer [count] = 0; /* e.g., if reading from a new file */
if (ferror (uptr->fileref)) /* did a host file system error occur? */
return io_error (cvptr, uptr); /* set up the data error status and stop the simulation */
if (ferror (uptr->fileref)) /* did a host file system error occur? */
return io_error (cvptr, uptr, uncorrectable_data_error); /* set up the data error status and stop the simulation */
next_sector (cvptr, uptr); /* address the next sector */
@ -1985,8 +1989,8 @@ if (cvptr->index < DL_WPSEC + offset) { /* was a partial sector
sim_fwrite (cvptr->buffer + offset, sizeof (uint16), /* write the sector to the file */
DL_WPSEC, uptr->fileref);
if (ferror (uptr->fileref)) /* did a host file system error occur? */
return io_error (cvptr, uptr); /* set up the data error status and stop the simulation */
if (ferror (uptr->fileref)) /* did a host file system error occur? */
return io_error (cvptr, uptr, uncorrectable_data_error); /* set up the data error status and stop the simulation */
next_sector (cvptr, uptr); /* address the next sector */
@ -2036,10 +2040,13 @@ return SCPE_OK;
error.
If the addresses are valid, the drive is checked to ensure that it is ready
for positioning. If it is, the the byte offset in the image file is
calculated from the CHS address, and the file is positioned. The disc
service is scheduled to begin the data transfer, and the routine returns TRUE
to indicate that the file position was set.
for positioning. If it is, the file is positioned to a byte offset in the
image file that is calculated from the CHS address. If positioning succeeds,
the disc service is scheduled to begin the data transfer, and the routine
returns TRUE to indicate that the file position is set. If positioning fails
with a host file system error, it is reported to the simulation console, and
the routine returns FALSE to indicate that an AGC (drive positioner) fault
occurred.
Implementation notes:
@ -2100,10 +2107,18 @@ else { /* we are ready to posit
cvptr->sector, model); /* (for inspection only) */
uptr->pos = TO_OFFSET (block); /* and then convert to a byte offset */
sim_fseek (uptr->fileref, uptr->pos, SEEK_SET); /* set the image file position */
if (sim_fseek (uptr->fileref, uptr->pos, SEEK_SET)) { /* set the image file position; if it failed */
io_error (cvptr, uptr, status_2_error); /* then report it to the simulation console */
uptr->wait = cvptr->data_time; /* delay for the data access time */
return TRUE; /* and report that positioning was accomplished */
dl_load_unload (cvptr, uptr, FALSE); /* unload the heads */
uptr->STAT |= DL_S2FAULT; /* and set Fault status */
}
else { /* otherwise the seek succeeded */
uptr->wait = cvptr->data_time; /* so delay for the data access time */
return TRUE; /* report that positioning was accomplished */
}
}
return FALSE; /* report that positioning failed or was deferred */
@ -2252,19 +2267,19 @@ return TRUE; /* and report that t
}
/* Report an I/O error.
/* Report a stream I/O error.
Errors indicated by the host file system are reported to the console, and
simulation is stopped with an "I/O error" message. If the simulation is
continued, the CPU will receive an Uncorrectable Data Error indication from
the controller.
continued, the CPU will receive the supplied status indication from the
controller.
*/
static t_stat io_error (CVPTR cvptr, UNIT *uptr)
static t_stat io_error (CVPTR cvptr, UNIT *uptr, CNTLR_STATUS status)
{
dl_end_command (cvptr, uncorrectable_data_error); /* terminate the command with an error */
dl_end_command (cvptr, status); /* terminate the command with an error */
perror ("DiscLib I/O error"); /* report the error to the console */
perror ("HP 2100 simulator disc library I/O error"); /* report the error to the console */
clearerr (uptr->fileref); /* and clear the error in case we resume */
return SCPE_IOERR; /* return an I/O error to stop the simulator */

View File

@ -1,6 +1,6 @@
/* hp_disclib.h: HP MAC/ICD disc controller simulator library definitions
/* hp_disclib.h: HP MAC/ICD disc controller simulator library declarations
Copyright (c) 2011-2016, J. David Bryan
Copyright (c) 2011-2017, J. David Bryan
Copyright (c) 2004-2011, Robert M. Supnik
Permission is hereby granted, free of charge, to any person obtaining a
@ -24,6 +24,7 @@
used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from the authors.
17-Jan-17 JDB Moved "hp2100_defs.h" inclusion to "hp2100_disclib.c"
13-May-16 JDB Modified for revised SCP API function parameter types
24-Oct-12 JDB Changed CNTLR_OPCODE to title case to avoid name clash
07-May-12 JDB Added end-of-track delay time as a controller variable
@ -38,10 +39,6 @@
#include "hp2100_defs.h"
/* Program limits */
#define DL_MAXDRIVE 7 /* last valid drive number */

View File

@ -1,6 +1,7 @@
/* hp2100_dp.c: HP 2100 12557A/13210A disk simulator
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"),
@ -26,6 +27,7 @@
DP 12557A 2870 disk subsystem
13210A 7900 disk subsystem
22-Apr-17 JDB Added fall-through comment for FNC_STA case in dpcio
09-Nov-16 JDB Corrected disk subsystem model number from 2871 to 2870
13-May-16 JDB Modified for revised SCP API function parameter types
30-Dec-14 JDB Added S-register parameters to ibl_copy
@ -647,6 +649,8 @@ while (working_set) {
if (dp_ctype == A13210) /* 13210? clr dch flag */
dpdio (&dpd_dib, ioCLF, 0);
/* fall into FNC_CHK and FNC_AR cases */
case FNC_CHK: /* check */
case FNC_AR: /* addr rec */
dp_god (fnc, drv, dpc_dtime); /* sched dch xfr */

View File

@ -1,6 +1,6 @@
/* hp2100_mpx.c: HP 12792C eight-channel asynchronous multiplexer simulator
Copyright (c) 2008-2016, J. David Bryan
Copyright (c) 2008-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"),
@ -25,6 +25,7 @@
MPX 12792C 8-channel multiplexer card
22-Apr-17 JDB Corrected missing compound statements
02-Aug-16 JDB Burst-fill only the first receive buffer in fast mode
28-Jul-16 JDB Fixed buffer ready check at read completion
Fixed terminate on character counts > 254
@ -1136,7 +1137,7 @@ switch (mpx_cmd) {
case CMD_CANCEL: /* cancel first read buffer */
port = key_to_port (mpx_portkey); /* get port */
if (port >= 0) /* port defined? */
if (port >= 0) { /* port defined? */
buf_cancel (ioread, port, get); /* cancel get buffer */
if (buf_avail (ioread, port) == 2) /* if all buffers are now clear */
@ -1144,6 +1145,7 @@ switch (mpx_cmd) {
else if (!(mpx_flags [port] & FL_RDFILL)) /* otherwise if the other buffer is not filling */
mpx_flags [port] |= FL_HAVEBUF; /* then indicate buffer availability */
}
break;
@ -1233,11 +1235,12 @@ switch (mpx_cmd) {
case CMD_SET_FLOW: /* set flow control */
port = key_to_port (mpx_portkey); /* get port */
if (port >= 0) /* port defined? */
if (port >= 0) { /* port defined? */
mpx_flowcntl [port] = mpx_param & FC_XONXOFF; /* save port flow control */
if (mpx_param & FC_FORCE_XON) /* force XON? */
mpx_flags [port] &= ~FL_XOFF; /* resume transmission if suspended */
}
break;

View File

@ -1,6 +1,6 @@
SIMH/HP 2100 RELEASE NOTES
==========================
Last update: 2017-01-11
Last update: 2017-05-01
This file documents the release history of the simulator for the Hewlett-Packard
@ -12,7 +12,7 @@ simulator code base is available at:
https://github.com/simh/simh
...and may be downloaded at any time. A code snapshot is identified by the "git
commit ID" that is displayed by the simulator welcome banner.
commit ID" that is displayed in the simulator welcome banner.
Therefore, HP 2100 releases are simply documentation checkpoints that describe
the changes that have occurred since the last checkpoint. Generally, a release
@ -22,6 +22,25 @@ of the next release document.
===============================
Reporting Bugs in the Simulator
===============================
If you find a bug in the HP 2100 simulator, please report it either to the SIMH
issue tracker on github at:
https://github.com/simh/simh/issues
...or to the SIMH mailing list; see:
http://mailman.trailing-edge.com/mailman/listinfo/simh
...for subscribing information. In either case, please include a console log
that contains a reproducible test case that illustrates the problem. See the
"Recording Simulator Activities" section of the "SIMH User's Guide" for details.
===================
General Information
===================
@ -35,11 +54,13 @@ diagnostic tests. See the accompanying "hp2100_diag.txt" file for details.
The simulator has been tested with the following operating systems:
- SIO, BCS, and MTS.
- 2000E, 2000F, and 2000/Access Time-Shared BASIC.
- DOS, DOS-M, and DOS-III.
- RTE-II, RTE-III, RTE-IVB, and RTE-6/VM.
- RTE, RTE-B, RTE-C, RTE-II, RTE-III, RTE-IV, RTE-IVB, and RTE-6/VM.
The user's manual for the simulator is provided in Microsoft Word format in the
"doc" subdirectory of the code base snapshot downloaded from the github site. A
@ -136,6 +157,148 @@ Revision 5010:
======================
Release 26, 2017-05-01
======================
This release of the HP 2100 simulator does not add any new features.
--------------------
Implementation Notes
--------------------
- Starting with the next release, the LOAD command will be rewritten to load
files containing absolute binary loaders into the protected address space of
the 21xx machines and configure the I/O instructions. The LOAD command is
not designed for general loading of absolute binary files, as it does not
initialize the A and B registers as some HP software expects. It is intended
only to install bootstrap loaders. The BOOT PTR command is the proper
simulation of the hardware absolute paper tape loader.
----------
Bugs Fixed
----------
1. PROBLEM: The RWCS debug option shown in the user's guide does not exist.
VERSION: Release 25.
OBSERVATION: The "HP2100 Simulator User's Guide" says that the RWCS debug
option may be specified for the DS and DA devices to trace "disk read/
write/control/status commands." However, entering a SET DS DEBUG=RWCS
command gives an "Invalid argument" error.
CAUSE: The option name is misspelled; the correct option is RWSC.
RESOLUTION: Modify "hp2100_doc.doc" to list the correct option name.
STATUS: Fixed in Release 26.
2. PROBLEM: Halt opcodes 1060xx and 1070xx do not display in mnemonic form.
VERSION: Release 25.
OBSERVATION: Halt instructions 106000-106077 and 107000-107077 are not
displayed in mnemonic form, either directly with an EXAMINE -M command
or in the message displayed for a programmed halt. These instruction
ranges are displayed in octal only.
CAUSE: Section 3.20, "Input/Output Instructions," of the "HP 1000
M/E/F-Series Computers Technical Reference Handbook" (HP 5955-0282, March
1980) says, in part, "Bit 11, where relevant, specifies the A- or
B-register or distinguishes between set control and clear control;
otherwise, bit 11 may be a logic 0 or a logic 1 without affecting the
instruction (although the assembler will assign zeros in this case)." The
HLT instruction does not specify the A/B register, so the valid opcodes are
102000-102077, 103000-103777, 106000-106077, and 107000-107077. However,
the latter two ranges are omitted from the "opcode" and "opc_val" tables
used for decoding.
RESOLUTION: Add the 1060xx/107xx range to the "opc_val" table and a second
"HLT" string to the "opcode" table (hp2100_sys.c) to permit mnemonic
display of this instruction range.
STATUS: Fixed in Release 26.
3. PROBLEM: The SFB (scan for byte) opcode displays as SBT (store byte).
VERSION: Release 25.
OBSERVATION: Entering the "EVAL -M 105767" command should display the
"SFB" mnemonic. Instead, it displays "SBT".
CAUSE: The entry in the opcode mnemonic table corresponding to the 105767
value is "SBT", which is incorrect. It should be "SFB" (SBT is 105764).
RESOLUTION: Modify the "opcode" table (hp2100_sys.c) to use the correct
mnemonic for the SFB instruction.
STATUS: Fixed in Release 26.
4. PROBLEM: Host file system seek errors are not caught.
VERSION: Release 25.
OBSERVATION: The MAC/ICD disc library checks for host file system read or
write errors and returns Uncorrectable Data Error status if an error is
indicated. However, host file system seeks are simply assumed to succeed;
no indication of an error is given if a call fails. A failed seek should
be detected, and a Drive Fault (positioner error) should be returned.
CAUSE: Oversight.
RESOLUTION: Modify "position_sector" (hp2100_disclib.c) to test the
"sim_fseek" call for error status and to simulate a Drive Fault (AGC error)
if the call fails.
STATUS: Fixed in Release 26.
5. PROBLEM: Set Flow Control and Cancel commands fail if port key is not set.
VERSION: Release 25.
OBSERVATION: HP 8-channel multiplexer commands that refer to ports do so
indirectly by passing a port key, rather than a port number. The
key-to-port translation is established by the "Set Port Key" command, which
must be executed before any port-specific commands. If a port key has not
been established, then all port-specific commands should be ignored.
However, the "Cancel first receive buffer" and "Set flow control" commands
cause program corruption if the key has not been set.
CAUSE: The test for key validity is improperly applied for these commands.
RESOLUTION: Modify "exec_command" (hp2100_mpx.c) to ignore these commands
if the port key has not been set.
STATUS: Fixed in Release 26.
6. ENHANCEMENT: Improve the EAU shift and rotate instruction simulations.
VERSION: Release 25.
OBSERVATION: The shift and rotate instructions (ASL, ASR, LSL, LSR, RRL,
and RRR) perform 32-bit operations on the combined B and A registers. The
original implementation treated the 16-bit registers independently.
However, it is faster and smaller to form a 32-bit operand, apply the
operation, and then split the operand back into the B and A registers.
Modern compilers, such as gcc, recognize the shifting and masking patterns
necessary for a rotation and generate a single rotate-left or rotate-right
machine instruction.
RESOLUTION: Modify "cpu_eau" (hp2100_cpu1.c) to reimplement the shift and
rotate instructions as 32-bit operations.
STATUS: Fixed in Release 26.
======================
Release 25, 2017-01-11
======================
@ -144,42 +307,42 @@ This is the initial checkpoint release of the HP 2100 simulator, corresponding
to the 25th set of changes to the 4.0 code base. The following devices are
currently simulated:
- 2114C CPU with up to 16 KW of memory
- 2115A CPU with up to 8 KW of memory
- 2116C CPU with up to 32 KW of memory
- 2100A CPU with up to 32 KW of memory
- 1000 M/E/F-Series CPU with up to 1024 KW of memory
- EAU, FP, IOP, DMS, FFP, DBI, VIS, and SIGNAL microcode extensions
- RTE-IV EMA or RTE-6/VM OS and VMA microcode extensions
- 12531C Buffered Teleprinter Interface with one 2752 Teleprinter
- 12539C Time Base Generator
- 12557A Disc Controller with four 2870 drives
- 12559C Magnetic Tape Controller with one 3030 drive
- 12565A Disc Controller with two 2883 drives
- 12566B Microcircuit Interface with a loopback connector
- 12578A Direct Memory Access Controller
- 12581A Memory Protect
- 12597A Duplex Register Interface with one 2748 Paper Tape Reader
- 12597A Duplex Register Interface with one 2895 Paper Tape Punch
- 12606B Fixed Head Disc Controller with one 2770/2771 drive
- 12607B Direct Memory Access Controller
- 12610B Drum Controller with one 2773/2774/2775 drive
- 12620A Privileged Interrupt Fence
- 12653A Printer Controller with one 2767 Line Printer
- 12792C 8-Channel Asynchronous Multiplexer
- 12821A Disc Interface with four 7906H/7920H/7925H drives
- 12845B Printer Controller with one 2607 Line Printer
- 12875A Interprocessor Link
- 12892B Memory Protect
- 12895A Direct Memory Access Controller
- 12897B Dual-Channel Port Controller
- 12920A 16-Channel Terminal Multiplexer
- 12936A Privileged Interrupt Fence
- 12966A Buffered Asynchronous Communications Interface
- 13037D Disc Controller with eight 7905/7906/7920/7925 drives
- 13181A Magnetic Tape Controller with four 7970B drives
- 13183A Magnetic Tape Controller with four 7970E drives
- 13210A Disc Controller with four 7900 drives
- 2114C CPU with up to 16 KW of memory
- 2115A CPU with up to 8 KW of memory
- 2116C CPU with up to 32 KW of memory
- 2100A CPU with up to 32 KW of memory
- 1000 M/E/F-Series CPU with up to 1024 KW of memory
- EAU, FP, IOP, DMS, FFP, DBI, VIS, and SIGNAL microcode extensions
- RTE-IV EMA or RTE-6/VM OS and VMA microcode extensions
- 12531C Buffered Teleprinter Interface with one 2752 Teleprinter
- 12539C Time Base Generator
- 12557A Disc Controller with four 2870 drives
- 12559C Magnetic Tape Controller with one 3030 drive
- 12565A Disc Controller with two 2883 drives
- 12566B Microcircuit Interface with a loopback connector
- 12578A Direct Memory Access Controller
- 12581A Memory Protect
- 12597A Duplex Register Interface with one 2748 Paper Tape Reader
- 12597A Duplex Register Interface with one 2895 Paper Tape Punch
- 12606B Fixed Head Disc Controller with one 2770/2771 drive
- 12607B Direct Memory Access Controller
- 12610B Drum Controller with one 2773/2774/2775 drive
- 12620A Privileged Interrupt Fence
- 12653A Printer Controller with one 2767 Line Printer
- 12792C 8-Channel Asynchronous Multiplexer
- 12821A Disc Interface with four 7906H/7920H/7925H drives
- 12845B Printer Controller with one 2607 Line Printer
- 12875A Interprocessor Link
- 12892B Memory Protect
- 12895A Direct Memory Access Controller
- 12897B Dual-Channel Port Controller
- 12920A 16-Channel Terminal Multiplexer
- 12936A Privileged Interrupt Fence
- 12966A Buffered Asynchronous Communications Interface
- 13037D Disc Controller with eight 7905/7906/7920/7925 drives
- 13181A Magnetic Tape Controller with four 7970B drives
- 13183A Magnetic Tape Controller with four 7970E drives
- 13210A Disc Controller with four 7900 drives
The "HP 2100 Simulator User's Guide" manual describes the configuration and
operation of each of these devices in detail.
@ -194,12 +357,11 @@ Implementation Notes
- Starting with the next release, the LOAD command will restrict its operation
to the addresses occupied by the bootstrap loaders, i.e., the last 64
locations in memory (up to 32K), unless forced by the addition of the "-F"
switch. The LOAD command is not designed for general loading of absolute
binary files, as it does not initialize the A and B registers as some HP
software expects. It is intended only to install bootstrap loaders. The
BOOT PTR command is the proper simulation of the hardware absolute paper tape
loader.
locations in memory (up to 32K). The LOAD command is not designed for
general loading of absolute binary files, as it does not initialize the A and
B registers as some HP software expects. It is intended only to install
bootstrap loaders. The BOOT PTR command is the proper simulation of the
hardware absolute paper tape loader.
----------

View File

@ -24,6 +24,8 @@
used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from Robert M Supnik.
15-Jan-17 JDB Corrected HLT decoding to add the 1060xx and 1070xx ranges
Corrected SFB decoding
14-Jan-17 JDB Removed use of Fprintf functions for version 4.x and on
30-Dec-16 JDB Corrected parsing of memory reference instructions
13-May-16 JDB Modified for revised SCP API function parameter types
@ -294,7 +296,7 @@ static const char *opcode[] = {
"FAD", "FSB", "FMP", "FDV",
"FIX", "FLT",
"STO", "CLO", "SOC", "SOS",
"HLT", "STF", "CLF",
"HLT", "HLT", "STF", "CLF", /* 2nd HLT is 1060xx and 1070xx ranges */
"SFC", "SFS", "MIA", "MIB",
"LIA", "LIB", "OTA", "OTB",
"STC", "CLC",
@ -319,7 +321,7 @@ static const char *opcode[] = {
"CYA", "CYB", "LDY",
"ADY", "XAY", "XBY",
"ISX", "DSX", "JLY", "LBT",
"SBT", "MBT", "CBT", "SBT",
"SBT", "MBT", "CBT", "SFB",
"ISY", "DSY", "JPY", "SBS",
"CBS", "TBS", "CMW", "MVW",
NULL, /* decode only */
@ -353,7 +355,7 @@ static const int32 opc_val[] = {
0105000+I_EMR, 0105020+I_EMR, 0105040+I_EMR, 0105060+I_EMR,
0105100+I_NPN, 0105120+I_NPN,
0102101+I_NPN, 0103101+I_NPN, 0102201+I_NPC, 0102301+I_NPC,
0102000+I_IO1, 0102100+I_IO2, 0103100+I_IO2,
0102000+I_IO1, 0106000+I_IO1, 0102100+I_IO2, 0103100+I_IO2,
0102200+I_IO1, 0102300+I_IO1, 0102400+I_IO1, 0106400+I_IO1,
0102500+I_IO1, 0106500+I_IO1, 0102600+I_IO1, 0106600+I_IO1,
0102700+I_IO1, 0106700+I_IO1,

Binary file not shown.