1
0
mirror of https://github.com/open-simh/simh.git synced 2026-04-29 05:15:30 +00:00

Notes For V3.4-0

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

1. New Features in 3.4

1.1 SCP and Libraries

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

1.2 Interdata

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

1.3 HP2100

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

2. Bugs Fixed in 3.4-0

2.1 Interdata

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

2.2 PDP-10

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

2.3 PDP-11

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

View File

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

View File

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

File diff suppressed because it is too large Load Diff

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

508
HP2100/hp2100_fp1.c Normal file
View File

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

52
HP2100/hp2100_fp1.h Normal file
View File

@@ -0,0 +1,52 @@
/* hp2100_fp1.h: HP 2100/21MX extended-precision floating point definitions
Copyright (c) 2005, J. David Bryan
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Except as contained in this notice, the name of the author shall not
be used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from the author.
*/
#ifndef _HP2100_FP1_H_
#define _HP2100_FP1_H_ 0
/* HP memory representation of an extended-precision number */
typedef struct { uint32 high;
uint32 low; } XPN;
#define AS_XPN(x) (*(XPN *) &(x)) /* view as XPN */
XPN ReadX (uint32 va);
void WriteX (uint32 va, XPN packed);
uint32 x_add (XPN *sum, XPN augend, XPN addend);
uint32 x_sub (XPN *difference, XPN minuend, XPN subtrahend);
uint32 x_mpy (XPN *product, XPN multiplicand, XPN multiplier);
uint32 x_div (XPN *quotient, XPN dividend, XPN divisor);
uint32 x_pak (XPN *result, XPN mantissa, int32 exponent);
uint32 x_com (XPN *mantissa);
uint32 x_dcm (XPN *packed);
void x_trun (XPN *result, XPN source);
#endif

View File

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