1
0
mirror of https://github.com/simh/simh.git synced 2026-03-07 03:25:59 +00:00

HP2100: HP 2100 release 27

See HP2100/hp2100_release.txt for details of the release
This commit is contained in:
Mark Pizzolato
2017-09-06 22:16:14 -07:00
parent 964195dd78
commit a6552b823d
37 changed files with 19075 additions and 9002 deletions

View File

@@ -1,6 +1,6 @@
/* hp2100_baci.c: HP 12966A buffered asynchronous communications interface simulator
/* hp2100_baci.c: HP 12966A Buffered Asynchronous Communications Interface simulator
Copyright (c) 2007-2016, J. David Bryan
Copyright (c) 2007-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,8 +23,12 @@
used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from the author.
BACI 12966A BACI card
BACI 12966A Buffered Asynchronous Communications Interface
15-Mar-17 JDB Trace flags are now global
Changed DEBUG_PRI calls to tprintfs
10-Mar-17 JDB Added IOBUS to the debug table
17-Jan-17 JDB Changed "hp_---sc" and "hp_---dev" to "hp_---_dib"
02-Aug-16 JDB "baci_poll_svc" now calls "tmxr_poll_conn" unilaterally
13-May-16 JDB Modified for revised SCP API function parameter types
24-Dec-14 JDB Added casts for explicit downward conversions
@@ -184,14 +188,6 @@
#define UNIT_CAPSLOCK (1 << UNIT_V_CAPSLOCK)
/* Debug flags */
#define DEB_CMDS (1 << 0) /* commands and status */
#define DEB_CPU (1 << 1) /* CPU I/O */
#define DEB_BUF (1 << 2) /* buffer gets and puts */
#define DEB_XFER (1 << 3) /* character reads and writes */
/* Bit flags */
#define OUT_MR 0100000 /* common master reset */
@@ -418,49 +414,51 @@ UNIT baci_unit[] = {
{ UDATA (&baci_poll_svc, UNIT_DIS, POLL_FIRST) } /* Telnet poll unit */
};
REG baci_reg[] = {
{ ORDATA (IBUF, baci_ibuf, 16), REG_FIT },
{ ORDATA (OBUF, baci_obuf, 16), REG_FIT },
{ ORDATA (STATUS, baci_status, 16), REG_FIT },
REG baci_reg [] = {
/* Macro Name Location Radix Width Offset Depth Flags */
/* ------ -------- -------------------- ----- ----- ------ ---------- --------------- */
{ ORDATA (IBUF, baci_ibuf, 16), REG_FIT | REG_X },
{ ORDATA (OBUF, baci_obuf, 16), REG_FIT | REG_X },
{ GRDATA (STATUS, baci_status, 2, 16, 0), REG_FIT },
{ ORDATA (EDSIW, baci_edsiw, 16), REG_FIT },
{ ORDATA (DSRW, baci_dsrw, 16), REG_FIT },
{ ORDATA (CFCW, baci_cfcw, 16), REG_FIT },
{ ORDATA (ICW, baci_icw, 16), REG_FIT },
{ ORDATA (ISRW, baci_isrw, 16), REG_FIT },
{ ORDATA (EDSIW, baci_edsiw, 16), REG_FIT },
{ ORDATA (DSRW, baci_dsrw, 16), REG_FIT },
{ ORDATA (CFCW, baci_cfcw, 16), REG_FIT },
{ ORDATA (ICW, baci_icw, 16), REG_FIT },
{ ORDATA (ISRW, baci_isrw, 16), REG_FIT },
{ DRDATA (FIFOPUT, baci_fput, 8) },
{ DRDATA (FIFOGET, baci_fget, 8) },
{ DRDATA (FIFOCNTR, baci_fcount, 8) },
{ DRDATA (BRKCNTR, baci_bcount, 16) },
{ DRDATA (FIFOPUT, baci_fput, 8) },
{ DRDATA (FIFOGET, baci_fget, 8) },
{ DRDATA (FIFOCNTR, baci_fcount, 8) },
{ DRDATA (BRKCNTR, baci_bcount, 16) },
{ BRDATA (FIFO, baci_fifo, 8, 8, FIFO_SIZE) },
{ BRDATA (SPCHAR, baci_spchar, 8, 1, 256) },
{ BRDATA (FIFO, baci_fifo, 8, 8, FIFO_SIZE), REG_A },
{ BRDATA (SPCHAR, baci_spchar, 8, 1, 256) },
{ ORDATA (UARTTHR, baci_uart_thr, 16), REG_FIT },
{ ORDATA (UARTTR, baci_uart_tr, 16), REG_NZ },
{ ORDATA (UARTRHR, baci_uart_rhr, 16), REG_FIT },
{ ORDATA (UARTRR, baci_uart_rr, 16), REG_NZ },
{ DRDATA (UARTCLK, baci_uart_clk, 16) },
{ ORDATA (UARTTHR, baci_uart_thr, 16), REG_FIT | REG_X },
{ ORDATA (UARTTR, baci_uart_tr, 16), REG_NZ | REG_X },
{ ORDATA (UARTRHR, baci_uart_rhr, 16), REG_FIT | REG_X },
{ ORDATA (UARTRR, baci_uart_rr, 16), REG_NZ | REG_X },
{ DRDATA (UARTCLK, baci_uart_clk, 16) },
{ DRDATA (CTIME, baci_term.wait, 19), REG_RO },
{ DRDATA (CTIME, baci_term.wait, 19) },
{ FLDATA (ENQFLAG, baci_enq_seen, 0), REG_HRO },
{ DRDATA (ENQCNTR, baci_enq_cntr, 16), REG_HRO },
{ FLDATA (ENQFLAG, baci_enq_seen, 0), REG_HRO },
{ DRDATA (ENQCNTR, baci_enq_cntr, 16), REG_HRO },
{ FLDATA (LKO, baci.lockout, 0) },
{ FLDATA (CTL, baci.control, 0) },
{ FLDATA (FLG, baci.flag, 0) },
{ FLDATA (FBF, baci.flagbuf, 0) },
{ FLDATA (SRQ, baci.srq, 0) },
{ ORDATA (SC, baci_dib.select_code, 6), REG_HRO },
{ ORDATA (DEVNO, baci_dib.select_code, 6), REG_HRO },
{ FLDATA (LKO, baci.lockout, 0) },
{ FLDATA (CTL, baci.control, 0) },
{ FLDATA (FLG, baci.flag, 0) },
{ FLDATA (FBF, baci.flagbuf, 0) },
{ FLDATA (SRQ, baci.srq, 0) },
{ ORDATA (SC, baci_dib.select_code, 6), REG_HRO },
{ ORDATA (DEVNO, baci_dib.select_code, 6), REG_HRO },
{ NULL }
};
MTAB baci_mod[] = {
{ UNIT_DIAG, UNIT_DIAG, "diagnostic mode", "DIAG", NULL, NULL, NULL },
{ UNIT_DIAG, 0, "terminal mode", "TERMINAL", NULL, NULL, NULL },
{ UNIT_DIAG, UNIT_DIAG, "diagnostic mode", "DIAGNOSTIC", NULL, NULL, NULL },
{ UNIT_DIAG, 0, "terminal mode", "TERMINAL", NULL, NULL, NULL },
{ UNIT_FASTTIME, UNIT_FASTTIME, "fast timing", "FASTTIME", NULL, NULL, NULL },
{ UNIT_FASTTIME, 0, "realistic timing", "REALTIME", NULL, NULL, NULL },
@@ -475,17 +473,18 @@ MTAB baci_mod[] = {
{ MTAB_XTD | MTAB_VDV | MTAB_NMO, 0, "STATISTICS", NULL, NULL, &tmxr_show_cstat, &baci_desc },
{ MTAB_XTD | MTAB_VDV, 0, NULL, "DISCONNECT", &tmxr_dscln, NULL, &baci_desc },
{ MTAB_XTD | MTAB_VDV, 0, "SC", "SC", &hp_setsc, &hp_showsc, &baci_dev },
{ MTAB_XTD | MTAB_VDV | MTAB_NMO, 0, "DEVNO", "DEVNO", &hp_setdev, &hp_showdev, &baci_dev },
{ MTAB_XTD | MTAB_VDV, 1u, "SC", "SC", &hp_set_dib, &hp_show_dib, (void *) &baci_dib },
{ MTAB_XTD | MTAB_VDV | MTAB_NMO, ~1u, "DEVNO", "DEVNO", &hp_set_dib, &hp_show_dib, (void *) &baci_dib },
{ 0 }
};
DEBTAB baci_deb[] = {
{ "CMDS", DEB_CMDS },
{ "CPU", DEB_CPU },
{ "BUF", DEB_BUF },
{ "XFER", DEB_XFER },
{ NULL, 0 }
DEBTAB baci_deb [] = {
{ "CMDS", DEB_CMDS },
{ "CPU", DEB_CPU },
{ "BUF", DEB_BUF },
{ "XFER", DEB_XFER },
{ "IOBUS", TRACE_IOBUS }, /* interface I/O bus signals and data words */
{ NULL, 0 }
};
DEVICE baci_dev = {
@@ -560,8 +559,7 @@ while (working_set) {
baci.flag = baci.flagbuf = CLEAR; /* clear flag and flag buffer */
baci.srq = CLEAR; /* clear SRQ */
if (DEBUG_PRI (baci_dev, DEB_CMDS))
fputs (">>BACI cmds: [CLF] Flag and SRQ cleared\n", sim_deb);
tprintf (baci_dev, DEB_CMDS, "[CLF] Flag and SRQ cleared\n");
update_status (); /* FLG might set when SRQ clears */
break;
@@ -572,8 +570,7 @@ while (working_set) {
baci.lockout = SET; /* set lockout */
baci.srq = SET; /* set SRQ */
if (DEBUG_PRI (baci_dev, DEB_CMDS))
fputs (">>BACI cmds: [STF] Flag, SRQ, and lockout set\n", sim_deb);
tprintf (baci_dev, DEB_CMDS, "[STF] Flag, SRQ, and lockout set\n");
break;
@@ -602,15 +599,15 @@ while (working_set) {
data = baci_ibuf; /* return received data */
if (DEBUG_PRI (baci_dev, DEB_CPU))
fprintf (sim_deb, ">>BACI cpu: [LIx%s] Received data = %06o\n", hold_or_clear, baci_ibuf);
tprintf (baci_dev, DEB_CPU, "[LIx%s] Received data = %06o\n",
hold_or_clear, baci_ibuf);
}
else { /* control clear? */
data = baci_status; /* return status */
if (DEBUG_PRI (baci_dev, DEB_CPU))
fprintf (sim_deb, ">>BACI cpu: [LIx%s] Status = %06o\n", hold_or_clear, baci_status);
tprintf (baci_dev, DEB_CPU, "[LIx%s] Status = %06o\n",
hold_or_clear, baci_status);
}
stat_data = IORETURN (SCPE_OK, data); /* merge in return status */
@@ -620,15 +617,14 @@ while (working_set) {
case ioIOO: /* I/O data output */
baci_obuf = IODATA (stat_data); /* get data value */
if (DEBUG_PRI (baci_dev, DEB_CPU))
fprintf (sim_deb, ">>BACI cpu: [OTx%s] Command = %06o\n", hold_or_clear, baci_obuf);
tprintf (baci_dev, DEB_CPU, "[OTx%s] Command = %06o\n",
hold_or_clear, baci_obuf);
if (baci_obuf & OUT_MR) { /* master reset? */
master_reset (); /* do before processing */
baci_io (&baci_dib, ioSIR, 0); /* set interrupt request */
if (DEBUG_PRI (baci_dev, DEB_CMDS))
fprintf (sim_deb, ">>BACI cmds: [OTx%s] Master reset\n", hold_or_clear);
tprintf (baci_dev, DEB_CMDS, "[OTx%s] Master reset\n", hold_or_clear);
}
switch (GET_ID (baci_obuf)) { /* isolate ID code */
@@ -639,10 +635,10 @@ while (working_set) {
fifo_put (ch); /* queue character */
if (baci_term.flags & UNIT_ATT) { /* attached to network? */
if (DEBUG_PRI (baci_dev, DEB_CMDS) && /* debugging? */
if (TRACING (baci_dev, DEB_CMDS) && /* debugging? */
(sim_is_active (&baci_term) == 0)) /* service stopped? */
fprintf (sim_deb, ">>BACI cmds: [OTx%s] Terminal service scheduled, "
"time = %d\n", hold_or_clear, baci_term.wait);
hp_trace (&baci_dev, DEB_CMDS, "[OTx%s] Terminal service scheduled, "
"time = %d\n", hold_or_clear, baci_term.wait);
if (baci_fcount == 1) /* first char to xmit? */
sim_activate_abs (&baci_term, /* start service with full char time */
@@ -683,17 +679,15 @@ while (working_set) {
sim_activate (&baci_term, /* activate I/O service */
baci_term.wait);
if (DEBUG_PRI (baci_dev, DEB_CMDS))
fprintf (sim_deb, ">>BACI cmds: [OTx%s] Terminal service scheduled, "
"time = %d\n", hold_or_clear, baci_term.wait);
tprintf (baci_dev, DEB_CMDS, "[OTx%s] Terminal service scheduled, "
"time = %d\n", hold_or_clear, baci_term.wait);
}
else { /* external rate */
sim_cancel (&baci_term); /* stop I/O service */
if (DEBUG_PRI (baci_dev, DEB_CMDS))
fprintf (sim_deb, ">>BACI cmds: [OTx%s] Terminal service stopped\n",
hold_or_clear);
tprintf (baci_dev, DEB_CMDS, "[OTx%s] Terminal service stopped\n",
hold_or_clear);
}
}
@@ -724,16 +718,14 @@ while (working_set) {
case ioCRS: /* control reset */
master_reset (); /* issue master reset */
if (DEBUG_PRI (baci_dev, DEB_CMDS))
fputs (">>BACI cmds: [CRS] Master reset\n", sim_deb);
tprintf (baci_dev, DEB_CMDS, "[CRS] Master reset\n");
break;
case ioCLC: /* clear control flip-flop */
baci.control = CLEAR; /* clear control */
if (DEBUG_PRI (baci_dev, DEB_CMDS))
fprintf (sim_deb, ">>BACI cmds: [CLC%s] Control cleared\n", hold_or_clear);
tprintf (baci_dev, DEB_CMDS, "[CLC%s] Control cleared\n", hold_or_clear);
break;
@@ -741,8 +733,7 @@ while (working_set) {
baci.control = SET; /* set control */
baci.lockout = CLEAR; /* clear lockout */
if (DEBUG_PRI (baci_dev, DEB_CMDS))
fprintf (sim_deb, ">>BACI cmds: [STC%s] Control set and lockout cleared\n", hold_or_clear);
tprintf (baci_dev, DEB_CMDS, "[STC%s] Control set and lockout cleared\n", hold_or_clear);
if (!(signal_set & ioCLF)) /* STC without ,C ? */
update_status (); /* clearing lockout might interrupt */
@@ -859,9 +850,8 @@ while (xmit_loop && (baci_uart_thr & IN_VALID)) { /* valid character in UA
baci_enq_cntr = baci_enq_cntr + 1; /* bump ENQ counter */
recv_loop = FALSE; /* skip recv to allow time before ACK */
if (DEBUG_PRI (baci_dev, DEB_XFER))
fprintf (sim_deb, ">>BACI xfer: Character ENQ absorbed internally, "
"ENQ count = %d\n", baci_enq_cntr);
tprintf (baci_dev, DEB_XFER, "Character ENQ absorbed internally, "
"ENQ count = %d\n", baci_enq_cntr);
}
else { /* character is not ENQ or not fast timing */
@@ -871,11 +861,9 @@ while (xmit_loop && (baci_uart_thr & IN_VALID)) { /* valid character in UA
status = tmxr_putc_ln (&baci_ldsc, /* transmit the character */
baci_uart_tr);
if ((status == SCPE_OK) && /* transmitted OK? */
DEBUG_PRI (baci_dev, DEB_XFER))
fprintf (sim_deb, ">>BACI xfer: Character %s "
"transmitted from UART\n",
fmt_char ((uint8) baci_uart_tr));
if (status == SCPE_OK) /* transmitted OK? */
tprintf (baci_dev, DEB_XFER, "Character %s transmitted from the UART\n",
fmt_char ((uint8) baci_uart_tr));
}
}
@@ -907,9 +895,8 @@ if (recv_loop && /* ok to process? */
baci_uart_rhr = baci_uart_rhr & ~IN_VALID; /* clear valid bit */
if (DEBUG_PRI (baci_dev, DEB_XFER))
fprintf (sim_deb, ">>BACI xfer: Deferred character %s processed\n",
fmt_char ((uint8) baci_uart_rhr));
tprintf (baci_dev, DEB_XFER, "Deferred character %s processed\n",
fmt_char ((uint8) baci_uart_rhr));
fifo_put ((uint8) baci_uart_rhr); /* move deferred character to FIFO */
baci_uart_rhr = CLEAR_HR; /* clear RHR */
@@ -928,8 +915,7 @@ while (recv_loop) { /* OK to process? */
if (baci_uart_rr & SCPE_BREAK) { /* break detected? */
baci_status = baci_status | IN_BREAK; /* set break status */
if (DEBUG_PRI (baci_dev, DEB_XFER))
fputs (">>BACI xfer: Break detected\n", sim_deb);
tprintf (baci_dev, DEB_XFER, "Break detected\n");
}
data_bits = 5 + (baci_cfcw & OUT_CHARSIZE); /* calculate number of data bits */
@@ -937,9 +923,8 @@ while (recv_loop) { /* OK to process? */
baci_uart_rhr = (uint16) (baci_uart_rr & data_mask); /* mask data into holding register */
baci_uart_rr = CLEAR_R; /* clear receiver register */
if (DEBUG_PRI (baci_dev, DEB_XFER))
fprintf (sim_deb, ">>BACI xfer: Character %s received by UART\n",
fmt_char ((uint8) baci_uart_rhr));
tprintf (baci_dev, DEB_XFER, "Character %s received by the UART\n",
fmt_char ((uint8) baci_uart_rhr));
if (baci_term.flags & UNIT_CAPSLOCK) /* caps lock mode? */
baci_uart_rhr = (uint16) toupper (baci_uart_rhr); /* convert to upper case if lower */
@@ -967,8 +952,7 @@ while (recv_loop) { /* OK to process? */
if (recv_loop && baci_enq_seen) { /* OK to process and ENQ seen? */
baci_enq_seen = FALSE; /* reset flag */
if (DEBUG_PRI (baci_dev, DEB_XFER))
fputs (">>BACI xfer: Character ACK generated internally\n", sim_deb);
tprintf (baci_dev, DEB_XFER, "Character ACK generated internally\n");
fifo_put (ACK); /* fake ACK from terminal */
update_status (); /* update FIFO status */
@@ -981,8 +965,7 @@ if ((baci_uart_thr & IN_VALID) || baci_enq_seen || /* more to transmit? */
tmxr_rqln (&baci_ldsc)) /* or more to receive? */
sim_activate (uptr, uptr->wait); /* reschedule service */
else
if (DEBUG_PRI (baci_dev, DEB_CMDS))
fputs (">>BACI cmds: Terminal service stopped\n", sim_deb);
tprintf (baci_dev, DEB_CMDS, "Terminal service stopped\n");
return status;
}
@@ -1179,48 +1162,37 @@ if ((baci_status & IN_STDIRQ) || /* standard interrupt? *
(baci_edsiw & OUT_ENCM) && /* and char mode */
(baci_fget != baci_fput)) { /* and FIFO not empty? */
if (baci.lockout) { /* interrupt lockout? */
if (DEBUG_PRI (baci_dev, DEB_CMDS))
fputs (">>BACI cmds: Lockout prevents flag set", sim_deb);
}
if (baci.lockout) /* interrupt lockout? */
tprintf (baci_dev, DEB_CMDS, "Lockout prevents flag set, status = %06o\n",
baci_status);
else if (baci.srq) { /* SRQ set? */
if (DEBUG_PRI (baci_dev, DEB_CMDS))
fputs (">>BACI cmds: SRQ prevents flag set", sim_deb);
}
else if (baci.srq) /* SRQ set? */
tprintf (baci_dev, DEB_CMDS, "SRQ prevents flag set, status = %06o\n",
baci_status);
else {
baci_io (&baci_dib, ioENF, 0); /* set flag */
if (DEBUG_PRI (baci_dev, DEB_CMDS))
fputs (">>BACI cmds: Flag and lockout set", sim_deb);
tprintf (baci_dev, DEB_CMDS, "Flag and lockout set, status = %06o\n",
baci_status);
}
if (DEBUG_PRI (baci_dev, DEB_CMDS))
fprintf (sim_deb, ", status = %06o\n", baci_status);
}
if ((baci_icw & OUT_DCPC) && /* DCPC enabled? */
((IO_MODE == XMIT) && (baci_fcount < 128) || /* and xmit and room in FIFO */
(IO_MODE == RECV) && (baci_fcount > 0))) { /* or recv and data in FIFO? */
if (baci.lockout) { /* interrupt lockout? */
if (DEBUG_PRI (baci_dev, DEB_CMDS))
fputs (">>BACI cmds: Lockout prevents SRQ set", sim_deb);
}
(IO_MODE == RECV) && (baci_fcount > 0))) /* or recv and data in FIFO? */
if (baci.lockout) /* interrupt lockout? */
tprintf (baci_dev, DEB_CMDS, "Lockout prevents SRQ set, status = %06o\n",
baci_status);
else {
baci.srq = SET; /* set SRQ */
baci_io (&baci_dib, ioSIR, 0); /* set interrupt request */
if (DEBUG_PRI (baci_dev, DEB_CMDS))
fputs (">>BACI cmds: SRQ set", sim_deb);
tprintf (baci_dev, DEB_CMDS, "SRQ set, status = %06o\n",
baci_status);
}
if (DEBUG_PRI (baci_dev, DEB_CMDS))
fprintf (sim_deb, ", status = %06o\n", baci_status);
}
return;
}
@@ -1340,10 +1312,9 @@ if ((baci_fget != baci_fput) || (baci_fcount >= 128)) { /* FIFO occupied? */
if (IO_MODE == RECV) /* receive mode? */
baci_fcount = baci_fcount - 1; /* decrement occupancy counter */
if (DEBUG_PRI (baci_dev, DEB_BUF))
fprintf (sim_deb, ">>BACI buf: Character %s get from FIFO [%d], "
"character counter = %d\n",
fmt_char ((uint8) data), baci_fget, baci_fcount);
tprintf (baci_dev, DEB_BUF, "Character %s get from FIFO [%d], "
"character counter = %d\n",
fmt_char ((uint8) data), baci_fget, baci_fcount);
baci_fget = (baci_fget + 1) % FIFO_SIZE; /* bump index modulo array size */
@@ -1354,9 +1325,8 @@ if ((baci_fget != baci_fput) || (baci_fcount >= 128)) { /* FIFO occupied? */
}
else /* FIFO empty */
if (DEBUG_PRI (baci_dev, DEB_BUF))
fprintf (sim_deb, ">>BACI buf: Attempted get on empty FIFO, "
"character count = %d\n", baci_fcount);
tprintf (baci_dev, DEB_BUF, "Attempted get on empty FIFO, "
"character count = %d\n", baci_fcount);
if (baci_fcount == 0) /* count now zero? */
baci_status = baci_status | IN_BUFEMPTY; /* set buffer empty flag */
@@ -1398,13 +1368,12 @@ else { /* RECV or THR occupied
baci_fcount = baci_fcount + 1; /* increment occupancy counter */
if (DEBUG_PRI (baci_dev, DEB_BUF))
if (pass_thru)
fprintf (sim_deb, ">>BACI buf: Character %s put to UART transmitter holding register, "
"character counter = 1\n", fmt_char (ch));
else
fprintf (sim_deb, ">>BACI buf: Character %s put to FIFO [%d], "
"character counter = %d\n", fmt_char (ch), index, baci_fcount);
if (pass_thru)
tprintf (baci_dev, DEB_BUF, "Character %s put to UART transmitter holding register, "
"character counter = 1\n", fmt_char (ch));
else
tprintf (baci_dev, DEB_BUF, "Character %s put to FIFO [%d], "
"character counter = %d\n", fmt_char (ch), index, baci_fcount);
if ((IO_MODE == RECV) && (baci_spchar [ch])) /* receive mode and special character? */
baci_status = baci_status | IN_SPCHAR; /* set special char seen flag */
@@ -1477,8 +1446,7 @@ if (baci_uart_clk > 0) { /* transfer in progress?
if (baci_bcount == 160) { /* break held long enough? */
baci_status = baci_status | IN_BREAK; /* set break flag */
if (DEBUG_PRI (baci_dev, DEB_XFER))
fputs (">>BACI xfer: Break detected\n", sim_deb);
tprintf (baci_dev, DEB_XFER, "Break detected\n");
}
}
@@ -1499,9 +1467,8 @@ if (baci_uart_clk > 0) { /* transfer in progress?
baci_uart_thr = fifo_get (); /* get next char into THR */
update_status (); /* update FIFO status */
if (DEBUG_PRI (baci_dev, DEB_XFER))
fprintf (sim_deb, ">>BACI xfer: UART transmitter empty, "
"holding register = %06o\n", baci_uart_thr);
tprintf (baci_dev, DEB_XFER, "UART transmitter empty, "
"holding register = %06o\n", baci_uart_thr);
}
else if ((IO_MODE == RECV) && /* receive mode? */
@@ -1517,10 +1484,8 @@ if (baci_uart_clk > 0) { /* transfer in progress?
baci_uart_rhr = (uint16) (baci_uart_rr >> (16 - uart_bits)); /* position data to right align */
baci_uart_rr = CLEAR_R; /* clear receiver register */
if (DEBUG_PRI (baci_dev, DEB_XFER))
fprintf (sim_deb, ">>BACI xfer: UART receiver = %06o (%s)\n",
baci_uart_rhr,
fmt_char ((uint8) (baci_uart_rhr & data_mask)));
tprintf (baci_dev, DEB_XFER, "UART receiver = %06o (%s)\n",
baci_uart_rhr, fmt_char ((uint8) (baci_uart_rhr & data_mask)));
fifo_put ((uint8) (baci_uart_rhr & data_mask)); /* put data in FIFO */
update_status (); /* update FIFO status */
@@ -1539,8 +1504,7 @@ if (baci_uart_clk > 0) { /* transfer in progress?
if (parity & 1) { /* parity error? */
baci_status = baci_status | IN_OVRUNPE; /* report it */
if (DEBUG_PRI (baci_dev, DEB_XFER))
fputs (">>BACI xfer: Parity error detected\n", sim_deb);
tprintf (baci_dev, DEB_XFER, "Parity error detected\n");
}
}
}
@@ -1578,19 +1542,17 @@ if ((baci_uart_clk == 0) && /* start of transfer? */
baci_uart_tr = (~data_mask | baci_uart_tr) << 2 | 1; /* form serial data stream */
if (DEBUG_PRI (baci_dev, DEB_XFER))
fprintf (sim_deb, ">>BACI xfer: UART transmitter = %06o (%s), "
"clock count = %d\n", baci_uart_tr & DMASK,
fmt_char ((uint8) (baci_uart_thr & data_mask)),
baci_uart_clk);
tprintf (baci_dev, DEB_XFER, "UART transmitter = %06o (%s), "
"clock count = %d\n", baci_uart_tr & DMASK,
fmt_char ((uint8) (baci_uart_thr & data_mask)),
baci_uart_clk);
}
else {
baci_uart_rr = CLEAR_R; /* clear receiver register */
if (DEBUG_PRI (baci_dev, DEB_XFER))
fprintf (sim_deb, ">>BACI xfer: UART receiver empty, "
"clock count = %d\n", baci_uart_clk);
tprintf (baci_dev, DEB_XFER, "UART receiver empty, "
"clock count = %d\n", baci_uart_clk);
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,28 +1,39 @@
/* hp2100_cpu.h: HP 2100 CPU definitions
/* hp2100_cpu.h: HP 2100 CPU declarations
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
AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Except as contained in this notice, the name of Robert M Supnik shall not
be used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from Robert M Supnik.
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 the authors.
22-Jul-17 JDB Renamed "intaddr" to CIR; added IR
14-Jul-17 JDB Removed calc_defer() prototype
11-Jul-17 JDB Moved "ibl_copy" and renamed to "cpu_ibl"
10-Jul-17 JDB Renamed the global routine "iogrp" to "cpu_iog"
07-Jul-17 JDB Changed "iotrap" from uint32 to t_bool
07-Jun-17 JDB Added maximum instruction length for sim_emax definition
06-Jun-17 JDB Added instruction group decoding macros
04-Apr-17 JDB Added "cpu_configuration" for symbolic ex/dep validation
08-Mar-17 JDB Added "cpu_speed" for TBG service access
15-Feb-17 JDB Deleted unneeded guard macro definition
05-Aug-16 JDB Renamed the P register from "PC" to "PR"
24-Dec-14 JDB Added casts for explicit downward conversions
18-Mar-13 JDB Added declarations for the MP abort handler and CPU registers
@@ -50,73 +61,213 @@
encode the series within the type.
*/
#ifndef HP2100_CPU_H_
#define HP2100_CPU_H_ 0
#include <setjmp.h>
/* CPU model definition flags */
#define CPU_V_SERIES 0
#define CPU_V_TYPE 2
#define CPU_V_FAMILY 3
/* Memory access macros.
#define FAMILY_21XX (0 << CPU_V_FAMILY)
#define FAMILY_1000 (1 << CPU_V_FAMILY)
These macros provide simplified function call sequences for memory reads and
writes by the CPU. They supply the correct access classification. The
following macro routines are provided:
#define TYPE_211X (0 << CPU_V_TYPE) /* 2114, 2115, 2116 */
#define TYPE_2100 (1 << CPU_V_TYPE) /* 2100A, 2100S */
#define TYPE_1000MEF (0 << CPU_V_TYPE) /* 1000-M, 1000-E, 1000-F */
#define TYPE_1000AL (1 << CPU_V_TYPE) /* 1000-L, A600, A700, A900, A990 */
Name Action
------- ------------------------------------------------------------
ReadF Read an instruction word using the current map
ReadW Read a data word using the current map
ReadWA Read a data word using the alternate map
ReadS Read a data word using the system map
ReadU Read a data word using the user map
ReadB Read a data byte using the current map
ReadBA Read a data byte using the alternate map
WriteW Write a data word using the current map
WriteWA Write a data word using the alternate map
WriteS Write a data word using the system map
WriteU Write a data word using the user map
WriteB Write a data byte using the current map
WriteBA Write a data byte using the alternate map
The MP_ABORT macro performs a "longjmp" to the memory protect handler in the
instruction execution loop. The parameter is the address of the violation.
The conditions that initiate a MP abort must be tested explicitly before
calling MP_ABORT.
*/
#define ReadF(a) mem_read (&cpu_dev, Fetch, a)
#define ReadW(a) mem_read (&cpu_dev, Data, a)
#define ReadWA(a) mem_read (&cpu_dev, Data_Alternate, a)
#define ReadS(a) mem_read (&cpu_dev, Data_System, a)
#define ReadU(a) mem_read (&cpu_dev, Data_User, a)
#define ReadB(a) mem_read_byte (&cpu_dev, Data, a)
#define ReadBA(a) mem_read_byte (&cpu_dev, Data_Alternate, a)
#define WriteW(a,v) mem_write (&cpu_dev, Data, a, v)
#define WriteWA(a,v) mem_write (&cpu_dev, Data_Alternate, a, v)
#define WriteS(a,v) mem_write (&cpu_dev, Data_System, a, v)
#define WriteU(a,v) mem_write (&cpu_dev, Data_User, a, v)
#define WriteB(a,v) mem_write_byte (&cpu_dev, Data, a, v)
#define WriteBA(a,v) mem_write_byte (&cpu_dev, Data_Alternate, a, v)
#define MP_ABORT(va) longjmp (save_env, (va))
/* CPU tracing flags */
#define DEBUG_NOOS (1u << 0) /* configure RTE-6/VM not to use OS firmware */
#define TRACE_INSTR (1u << 1) /* trace instruction executions */
#define TRACE_DATA (1u << 2) /* trace memory data accesses */
#define TRACE_FETCH (1u << 3) /* trace memory instruction fetches */
#define TRACE_REG (1u << 4) /* trace register values */
#define TRACE_OPND (1u << 5) /* trace instruction operands */
#define TRACE_EXEC (1u << 6) /* trace matching instruction execution states */
#define TRACE_SR (1u << 7) /* trace service requests received */
#define TRACE_ALL ~DEBUG_NOOS /* trace everything */
#define DMS_FORMAT "%c %04o %05o %06o " /* map | physical page | logical address | value format */
#define REGA_FORMAT "%c **** %05o %06o " /* protection | fence | S register format for working registers */
#define REGB_FORMAT "%c **** ***** ****** " /* protection format for MP/MEM registers */
#define OPND_FORMAT "* **** %05o %06o " /* address | data format for operands */
#define EXEC_FORMAT "******************** " /* null format for EXEC separation */
/* CPU stop flags */
#define SS_INHIBIT (t_stat) (~0u) /* inhibit stops for the first instruction executed */
#define STOP(s) ((s) & ~cpu_ss_inhibit) /* stop if the condition is enabled and not inhibited */
/* Supported breakpoint switches */
#define BP_EXEC (SWMASK ('E')) /* an execution breakpoint */
#define BP_ENONE (SWMASK ('N')) /* an execution breakpoint when mapping is off */
#define BP_ESYS (SWMASK ('S')) /* an execution breakpoint in the system map */
#define BP_EUSER (SWMASK ('U')) /* an execution breakpoint in the user map */
#define BP_SUPPORTED (BP_EXEC | BP_ENONE | BP_ESYS | BP_EUSER)
/* CPU unit flags.
31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
| R | - | G | V | O | E | D | F | M | I | P | U | CPU model |
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
| f | t | series|
+---+---+---+---+
Where:
R = reserved
G = SIGNAL/1000 firmware is present
V = Vector Instruction Set firmware is present
O = RTE-6/VM VMA and OS firmware is present
E = RTE-IV EMA firmware is present
D = Double Integer firmware is present
F = Fast FORTRAN Processor firmware is present
M = Dynamic Mapping System firmware is present
I = 2000 I/O Processor firmware is present
P = Floating Point hardware or firmware is present
U = Extended Arithmetic Unit is present
f = CPU family
t = CPU type
CPU Models:
0 0 00 = HP 2116
0 0 01 = HP 2115
0 0 10 = HP 2114
0 0 11 = unused
0 1 00 = HP 2100
0 1 01 = unused
0 1 10 = unused
0 1 11 = unused
1 0 00 = HP 1000 M-Series
1 0 01 = HP 1000 E-Series
1 0 10 = HP 1000 F-Series
1 0 11 = unused
1 1 00 = unused (1000 A-Series)
1 1 01 = unused (1000 A-Series)
1 1 10 = unused (1000 A-Series)
1 1 11 = unused (1000 A-Series)
*/
#define CPU_V_SERIES 0
#define CPU_V_TYPE 2
#define CPU_V_FAMILY 3
#define FAMILY_21XX (0 << CPU_V_FAMILY)
#define FAMILY_1000 (1 << CPU_V_FAMILY)
#define TYPE_211X (0 << CPU_V_TYPE) /* 2114, 2115, 2116 */
#define TYPE_2100 (1 << CPU_V_TYPE) /* 2100A, 2100S */
#define TYPE_1000MEF (0 << CPU_V_TYPE) /* 1000-M, 1000-E, 1000-F */
#define TYPE_1000AL (1 << CPU_V_TYPE) /* 1000-L, A600, A700, A900, A990 */
#define SERIES_16 (0 << CPU_V_SERIES) /* 211X */
#define SERIES_15 (1 << CPU_V_SERIES) /* 211X */
#define SERIES_14 (2 << CPU_V_SERIES) /* 211X */
#define SERIES_00 (0 << CPU_V_SERIES) /* 2100 */
#define SERIES_M (0 << CPU_V_SERIES) /* 1000 */
#define SERIES_E (1 << CPU_V_SERIES) /* 1000 */
#define SERIES_F (2 << CPU_V_SERIES) /* 1000 */
#define SERIES_16 (0 << CPU_V_SERIES) /* 211X */
#define SERIES_15 (1 << CPU_V_SERIES) /* 211X */
#define SERIES_14 (2 << CPU_V_SERIES) /* 211X */
#define SERIES_00 (0 << CPU_V_SERIES) /* 2100 */
#define SERIES_M (0 << CPU_V_SERIES) /* 1000 */
#define SERIES_E (1 << CPU_V_SERIES) /* 1000 */
#define SERIES_F (2 << CPU_V_SERIES) /* 1000 */
/* CPU unit flags */
#define UNIT_M_CPU 017 /* CPU model mask [3:0] */
#define UNIT_M_TYPE 014 /* CPU type mask [3:2] */
#define UNIT_M_FAMILY 010 /* CPU family mask [3:3] */
#define UNIT_M_CPU 017 /* CPU model mask [3:0] */
#define UNIT_M_TYPE 014 /* CPU type mask [3:2] */
#define UNIT_M_FAMILY 010 /* CPU family mask [3:3] */
#define UNIT_V_CPU (UNIT_V_UF + 0) /* CPU model bits 0-3 */
#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_V_DBI (UNIT_V_UF + 9) /* DBI installed */
#define UNIT_V_EMA (UNIT_V_UF + 10) /* RTE-4 EMA installed */
#define UNIT_V_VMAOS (UNIT_V_UF + 11) /* RTE-6 VMA/OS installed */
#define UNIT_V_VIS (UNIT_V_UF + 12) /* VIS installed */
#define UNIT_V_SIGNAL (UNIT_V_UF + 13) /* SIGNAL/1000 installed */
#define UNIT_V_CPU (UNIT_V_UF + 0) /* CPU model bits 0-3 */
#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_V_DBI (UNIT_V_UF + 9) /* DBI installed */
#define UNIT_V_EMA (UNIT_V_UF + 10) /* RTE-4 EMA installed */
#define UNIT_V_VMAOS (UNIT_V_UF + 11) /* RTE-6 VMA/OS installed */
#define UNIT_V_VIS (UNIT_V_UF + 12) /* VIS installed */
#define UNIT_V_SIGNAL (UNIT_V_UF + 13) /* SIGNAL/1000 installed */
/* Future microcode expansion; reuse flags bottom-up if needed */
#define UNIT_V_DS (UNIT_V_UF + 14) /* DS installed */
#define UNIT_V_DS (UNIT_V_UF + 14) /* DS installed */
/* Unit models */
#define UNIT_MODEL_MASK (UNIT_M_CPU << UNIT_V_CPU)
#define UNIT_MODEL_MASK (UNIT_M_CPU << UNIT_V_CPU)
#define UNIT_2116 ((FAMILY_21XX | TYPE_211X | SERIES_16) << UNIT_V_CPU)
#define UNIT_2115 ((FAMILY_21XX | TYPE_211X | SERIES_15) << UNIT_V_CPU)
#define UNIT_2114 ((FAMILY_21XX | TYPE_211X | SERIES_14) << UNIT_V_CPU)
#define UNIT_2100 ((FAMILY_21XX | TYPE_2100 | SERIES_00) << UNIT_V_CPU)
#define UNIT_1000_M ((FAMILY_1000 | TYPE_1000MEF | SERIES_M) << UNIT_V_CPU)
#define UNIT_1000_E ((FAMILY_1000 | TYPE_1000MEF | SERIES_E) << UNIT_V_CPU)
#define UNIT_1000_F ((FAMILY_1000 | TYPE_1000MEF | SERIES_F) << UNIT_V_CPU)
#define UNIT_2116 ((FAMILY_21XX | TYPE_211X | SERIES_16) << UNIT_V_CPU)
#define UNIT_2115 ((FAMILY_21XX | TYPE_211X | SERIES_15) << UNIT_V_CPU)
#define UNIT_2114 ((FAMILY_21XX | TYPE_211X | SERIES_14) << UNIT_V_CPU)
#define UNIT_2100 ((FAMILY_21XX | TYPE_2100 | SERIES_00) << UNIT_V_CPU)
#define UNIT_1000_M ((FAMILY_1000 | TYPE_1000MEF | SERIES_M) << UNIT_V_CPU)
#define UNIT_1000_E ((FAMILY_1000 | TYPE_1000MEF | SERIES_E) << UNIT_V_CPU)
#define UNIT_1000_F ((FAMILY_1000 | TYPE_1000MEF | SERIES_F) << UNIT_V_CPU)
/* Unit types */
#define UNIT_TYPE_MASK (UNIT_M_TYPE << UNIT_V_CPU)
#define UNIT_TYPE_MASK (UNIT_M_TYPE << UNIT_V_CPU)
#define UNIT_TYPE_211X ((FAMILY_21XX | TYPE_211X) << UNIT_V_CPU)
#define UNIT_TYPE_2100 ((FAMILY_21XX | TYPE_2100) << UNIT_V_CPU)
#define UNIT_TYPE_1000 ((FAMILY_1000 | TYPE_1000MEF) << UNIT_V_CPU)
#define UNIT_TYPE_211X ((FAMILY_21XX | TYPE_211X) << UNIT_V_CPU)
#define UNIT_TYPE_2100 ((FAMILY_21XX | TYPE_2100) << UNIT_V_CPU)
#define UNIT_TYPE_1000 ((FAMILY_1000 | TYPE_1000MEF) << UNIT_V_CPU)
/* Unit families */
@@ -125,92 +276,264 @@
#define UNIT_FAMILY_21XX (FAMILY_21XX << UNIT_V_CPU)
#define UNIT_FAMILY_1000 (FAMILY_1000 << UNIT_V_CPU)
/* Unit accessors */
#define UNIT_CPU_MODEL (cpu_unit.flags & UNIT_MODEL_MASK)
#define UNIT_CPU_TYPE (cpu_unit.flags & UNIT_TYPE_MASK)
#define UNIT_CPU_FAMILY (cpu_unit.flags & UNIT_FAMILY_MASK)
#define UNIT_CPU_MODEL (cpu_unit.flags & UNIT_MODEL_MASK)
#define UNIT_CPU_TYPE (cpu_unit.flags & UNIT_TYPE_MASK)
#define UNIT_CPU_FAMILY (cpu_unit.flags & UNIT_FAMILY_MASK)
#define CPU_MODEL_INDEX (UNIT_CPU_MODEL >> UNIT_V_CPU)
#define CPU_MODEL_INDEX (UNIT_CPU_MODEL >> UNIT_V_CPU)
/* Unit features */
#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_DBI (1 << UNIT_V_DBI)
#define UNIT_EMA (1 << UNIT_V_EMA)
#define UNIT_VMAOS (1 << UNIT_V_VMAOS)
#define UNIT_VIS (1 << UNIT_V_VIS)
#define UNIT_DS (1 << UNIT_V_DS)
#define UNIT_SIGNAL (1 << UNIT_V_SIGNAL)
#define UNIT_EAU (1u << UNIT_V_EAU)
#define UNIT_FP (1u << UNIT_V_FP)
#define UNIT_IOP (1u << UNIT_V_IOP)
#define UNIT_DMS (1u << UNIT_V_DMS)
#define UNIT_FFP (1u << UNIT_V_FFP)
#define UNIT_DBI (1u << UNIT_V_DBI)
#define UNIT_EMA (1u << UNIT_V_EMA)
#define UNIT_VMAOS (1u << UNIT_V_VMAOS)
#define UNIT_VIS (1u << UNIT_V_VIS)
#define UNIT_DS (1u << UNIT_V_DS)
#define UNIT_SIGNAL (1u << UNIT_V_SIGNAL)
#define UNIT_EMA_VMA (UNIT_EMA | UNIT_VMAOS)
#define UNIT_EMA_VMA (UNIT_EMA | UNIT_VMAOS)
#define UNIT_OPTS (UNIT_EAU | UNIT_FP | UNIT_IOP | \
UNIT_DMS | UNIT_FFP | UNIT_DBI | \
UNIT_EMA | UNIT_VMAOS | \
UNIT_VIS | UNIT_DS | UNIT_SIGNAL)
#define UNIT_OPTS (UNIT_EAU | UNIT_FP | UNIT_IOP | \
UNIT_DMS | UNIT_FFP | UNIT_DBI | \
UNIT_EMA | UNIT_VMAOS | \
UNIT_VIS | UNIT_DS | UNIT_SIGNAL)
/* "Pseudo-option" flags used only for option testing; never set into UNIT structure. */
#define UNIT_V_PFAIL (UNIT_V_UF - 1) /* Power fail installed */
#define UNIT_V_DMA (UNIT_V_UF - 2) /* DMA installed */
#define UNIT_V_MP (UNIT_V_UF - 3) /* Memory protect installed */
#define UNIT_V_PFAIL (UNIT_V_UF - 1) /* Power fail installed */
#define UNIT_V_DMA (UNIT_V_UF - 2) /* DMA installed */
#define UNIT_V_MP (UNIT_V_UF - 3) /* Memory protect installed */
#define UNIT_PFAIL (1 << UNIT_V_PFAIL)
#define UNIT_DMA (1 << UNIT_V_DMA)
#define UNIT_MP (1 << UNIT_V_MP)
#define UNIT_PFAIL (1 << UNIT_V_PFAIL)
#define UNIT_DMA (1 << UNIT_V_DMA)
#define UNIT_MP (1 << UNIT_V_MP)
#define UNIT_NONE 0 /* no options */
#define UNIT_NONE 0 /* no options */
/* Debug flags */
#define DEB_OS (1 << 0) /* RTE-6/VM OS firmware non-TBG processing */
#define DEB_OSTBG (1 << 1) /* RTE-6/VM OS firmware TBG processing */
#define DEB_VMA (1 << 2) /* RTE-6/VM VMA firmware instructions */
#define DEB_EMA (1 << 3) /* RTE-6/VM EMA firmware instructions */
#define DEB_VIS (1 << 4) /* E/F-Series VIS firmware instructions */
#define DEB_SIG (1 << 5) /* F-Series SIGNAL/1000 firmware instructions */
/* CPU configuration model flags */
#define CPU_MASK D16_MASK
#define CPU_2116 (1u << (FAMILY_21XX | TYPE_211X | SERIES_16))
#define CPU_2115 (1u << (FAMILY_21XX | TYPE_211X | SERIES_15))
#define CPU_2114 (1u << (FAMILY_21XX | TYPE_211X | SERIES_14))
#define CPU_2100 (1u << (FAMILY_21XX | TYPE_2100 | SERIES_00))
#define CPU_1000_M (1u << (FAMILY_1000 | TYPE_1000MEF | SERIES_M))
#define CPU_1000_E (1u << (FAMILY_1000 | TYPE_1000MEF | SERIES_E))
#define CPU_1000_F (1u << (FAMILY_1000 | TYPE_1000MEF | SERIES_F))
#define CPU_1000 (CPU_1000_M | CPU_1000_E | CPU_1000_F)
#define CPU_ALL (CPU_2116 | CPU_2115 | CPU_2114 | \
CPU_2100 | \
CPU_1000_M | CPU_1000_E | CPU_1000_F)
/* PC queue. */
#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] = (uint16) err_PC
#define PCQ_ENTRY pcq [pcq_p = (pcq_p - 1) & PCQ_MASK] = (uint16) err_PC
/* Memory reference instructions */
#define I_IA 0100000 /* indirect address */
#define I_AB 0004000 /* A/B select */
#define I_CP 0002000 /* current page */
#define I_DISP 0001777 /* page displacement */
#define I_PAGENO 0076000 /* page number */
/* Maximum instruction length.
This value is the length in words of the longest machine instruction. It is
used to set "sim_emax", which, in turn, is used to allocate the "sim_eval"
array. This array holds the words of a machine instruction to be formatted
and printed or to be parsed and stored.
The longest instruction in the 21xx/1000 family is the [D]VPIV (vector pivot)
instruction in the Vector Instruction Set.
*/
#define MAX_INSTR_LENGTH 10
/* Instruction group decoding.
The HP 21xx/1000 instruction set consists of five groups: the Memory
Reference Group (MRG), the Shift-Rotate Group (SRG), the Alter-Skip Group
(ASG), the I/O Group (IOG), and the Macro Group (MAC). Group membership is
determined by a multi-level decoding of bits 15-10, as follows:
Bits
15-10 Group
------ -----
xnnnx MRG
00000 SRG
00001 ASG
10001 IOG
10000 MAC
Where:
x = 0 or 1
n = any collective value other than 0
The MAC group is subdivided into the Extended Arithmetic Group (EAG), the
first User Instruction Group (UIG-0), and the second User Instruction Group
(UIG-1). Decoding is by bits 11-8, as follows (note that bit 10 = 0 for the
MAC group):
Bits
11-8 Group
---- -----
0000 EAG
0001 EAG
0010 EAG
0011 UIG-1
1000 EAG
1001 EAG
1010 UIG-0
1011 UIG-1
Bits 7-4 further decode the UIG instruction feature group.
*/
#define GROUP_MASK 0172000u /* instruction group mask */
#define MRG 0070000u /* Memory Reference Group indicator */
#define SRG 0000000u /* Shift-Rotate Group indicator */
#define ASG 0002000u /* Alter-Skip Group indicator */
#define IOG 0102000u /* I/O Group indicator */
#define MRGOP(v) (((v) & MRG) != 0) /* MRG membership test */
#define SRGOP(v) (((v) & GROUP_MASK) == SRG) /* SRG membership test */
#define ASGOP(v) (((v) & GROUP_MASK) == ASG) /* ASG membership test */
#define IOGOP(v) (((v) & GROUP_MASK) == IOG) /* IOG membership test */
#define SRG_CLE 0000040u /* SRG CLE opcode */
#define SRG_SLx 0000010u /* SRG SLA/SLB opcode */
#define SRG_NOP 0000000u /* SRG no-operation opcode */
#define SRG1_DE_MASK 0001000u /* SRG disable/enable first micro-op field bit */
#define SRG1_MASK 0001700u
#define SRG1_SHIFT 6
#define SRG2_DE_MASK 0000020u /* SRG disable/enable second micro-op field bit */
#define SRG2_MASK 0000027u
#define SRG2_SHIFT 0
#define SRG1(u) (((u) & SRG1_MASK) >> SRG1_SHIFT)
#define SRG2(u) (((u) & SRG2_MASK) >> SRG2_SHIFT)
#define UIG_MASK 0000360u /* UIG feature group mask */
#define UIG_SHIFT 4 /* UIG feature group alignment shift */
#define UIG(i) (((i) & UIG_MASK) >> UIG_SHIFT)
#define UIG_0_MASK 0177400u /* UIG-0 opcode mask */
#define UIG_0_RANGE 0105000u /* UIG-0 opcode range */
#define UIG_1_MASK 0173400u /* UIG-1 opcode mask */
#define UIG_1_RANGE 0101400u /* UIG-1 opcode range */
#define UIG_0_OP(i) (((i) & UIG_0_MASK) == UIG_0_RANGE) /* UIG-0 membership test */
#define UIG_1_OP(i) (((i) & UIG_1_MASK) == UIG_1_RANGE) /* UIG-1 membership test */
#define RTE_IRQ_RANGE 0105354 /* RTE-6/VM interrupt request instructions range */
/* Memory Reference Group instructions */
#define I_IA 0100000u /* indirect address */
#define I_AB 0004000u /* A/B select */
#define I_CP 0002000u /* current page */
#define I_DISP 0001777u /* page displacement */
#define I_PAGENO 0076000u /* page number */
/* Alter/Skip Group instructions */
#define I_CMx 0001000u /* CMA/B */
#define I_CLx 0000400u /* CLA/B */
#define I_CME 0000200u /* CME */
#define I_CLE 0000100u /* CLE */
#define I_SEZ 0000040u /* SEZ */
#define I_SSx 0000020u /* SSA/B */
#define I_SLx 0000010u /* SLA/B */
#define I_INx 0000004u /* INA/B */
#define I_SZx 0000002u /* SZA/B */
#define I_RSS 0000001u /* RSS */
#define I_SSx_SLx_RSS (I_SSx | I_SLx | I_RSS) /* a special case */
#define I_ALL_SKIPS (I_SEZ | I_SZx | I_SSx_SLx_RSS) /* another special case */
/* Shift/Rotate Group micro-ops */
#define I_xLS 0000000u /* ALS/BLS */
#define I_xRS 0000001u /* ARS/BRS */
#define I_RxL 0000002u /* RAL/RBL */
#define I_RxR 0000003u /* RAR/RBR */
#define I_xLR 0000004u /* ALR/BLR */
#define I_ERx 0000005u /* ERA/ERB */
#define I_ELx 0000006u /* ELA/ELB */
#define I_xLF 0000007u /* ALF/BLF */
#define SRG_DIS 0000000u
#define SRG1_EN 0000010u
#define SRG2_EN 0000020u
/* Other instructions */
#define I_NMRMASK 0172000 /* non-mrf opcode */
#define I_ASKP 0002000 /* alter/skip */
#define I_IO 0102000 /* I/O */
#define I_CTL 0004000 /* CTL on/off */
#define I_HC 0001000 /* hold/clear */
#define I_DEVMASK 0000077 /* device select code mask */
#define I_GETIOOP(x) (((x) >> 6) & 07) /* I/O sub op */
#define I_NOP 0000000u /* no operation */
#define I_NMRMASK 0172000u /* non-mrf opcode */
#define I_ASKP 0002000u /* alter/skip */
#define I_IO 0102000u /* I/O */
#define I_CTL 0004000u /* CTL on/off */
#define I_HC 0001000u /* hold/clear */
#define I_DEVMASK 0000077u /* device select code mask */
#define I_GETIOOP(x) (((x) >> 6) & 07u) /* I/O sub op */
/* Instruction masks */
#define I_MRG 0074000 /* MRG instructions */
#define I_MRG 0074000u /* MRG instructions */
#define I_MRG_I (I_MRG | I_IA) /* MRG indirect instruction group */
#define I_JSB 0014000 /* JSB instruction */
#define I_JSB 0014000u /* JSB instruction */
#define I_JSB_I (I_JSB | I_IA) /* JSB,I instruction */
#define I_JMP 0024000 /* JMP instruction */
#define I_ISZ 0034000 /* ISZ instruction */
#define I_JMP 0024000u /* JMP instruction */
#define I_ISZ 0034000u /* ISZ instruction */
#define I_IOG 0107700u /* I/O group instruction */
#define I_SFS 0102300u /* SFS instruction */
#define I_STF 0102100u /* STF instruction */
/* IBL assignments */
#define IBL_V_SEL 14 /* ROM select <15:14> */
#define IBL_M_SEL 03
#define IBL_PTR 0000000u /* ROM 0: 12992K paper tape reader (PTR) */
#define IBL_DP 0040000u /* ROM 1: 12992A 7900 disc (DP) */
#define IBL_DQ 0060000u /* ROM 1: 12992A 2883 disc (DQ) */
#define IBL_MS 0100000u /* ROM 2: 12992D 7970 tape (MS) */
#define IBL_DS 0140000u /* ROM 3: 12992B 7905/06/20/25 disc (DS) */
#define IBL_MAN 0010000u /* RPL/manual boot <13:12> */
#define IBL_V_DEV 6 /* select code <11:6> */
#define IBL_OPT 0000070u /* options in <5:3> */
#define IBL_DP_REM 0000001u /* DP removable <0:0> */
#define IBL_DS_HEAD 0000003u /* DS head number <1:0> */
#define IBL_LNT 64 /* boot ROM length in words */
#define IBL_MASK (IBL_LNT - 1) /* boot length mask */
#define IBL_DPC (IBL_LNT - 2) /* DMA ctrl word */
#define IBL_END (IBL_LNT - 1) /* last location */
#define IBL_S_CLR 0000000u /* cpu_ibl mask to clear the S register */
#define IBL_S_NOCLR 0177777u /* cpu_ibl mask to preserve the S register */
#define IBL_S_NOSET 0000000u /* cpu_ibl mask to preserve the S register */
#define IBL_SET_SC(s) ((HP_WORD) ((s) << IBL_V_DEV)) /* position the select code in the S register */
typedef MEMORY_WORD BOOT_ROM [IBL_LNT]; /* boot ROM data */
#define I_IOG 0107700 /* I/O group instruction */
#define I_SFS 0102300 /* SFS instruction */
#define I_STF 0102100 /* STF instruction */
/* Memory management */
@@ -243,17 +566,19 @@
#define MAP_N_PAG (PA_N_SIZE - VA_N_OFF) /* page width */
#define MAP_V_PAG (VA_N_OFF)
#define MAP_M_PAG ((1 << MAP_N_PAG) - 1)
#define MAP_GETPAG(x) (((x) & MAP_M_PAG) << MAP_V_PAG)
#define MAP_PAGE(r) ((r) & MAP_M_PAG) /* extract the page number from a map register */
#define TO_PAGE(n) ((n) << MAP_V_PAG) /* position the page number in a physical address */
/* MEM status register */
#define MST_ENBI 0100000 /* MEM enabled at interrupt */
#define MST_UMPI 0040000 /* User map selected at inerrupt */
#define MST_ENB 0020000 /* MEM enabled currently */
#define MST_UMP 0010000 /* User map selected currently */
#define MST_PRO 0004000 /* Protected mode enabled currently */
#define MST_FLT 0002000 /* Base page portion mapped */
#define MST_FENCE 0001777 /* Base page fence */
#define MST_ENBI 0100000u /* MEM enabled at interrupt */
#define MST_UMPI 0040000u /* User map selected at interrupt */
#define MST_ENB 0020000u /* MEM enabled currently */
#define MST_UMP 0010000u /* User map selected currently */
#define MST_PRO 0004000u /* Protected mode enabled currently */
#define MST_FLT 0002000u /* Base page portion mapped */
#define MST_FENCE 0001777u /* Base page fence */
/* MEM violation register */
@@ -261,76 +586,103 @@
#define MVI_V_WPR 14 /* MAP_V_xPR */
#define MVI_RPR (1 << MVI_V_RPR) /* rd viol */
#define MVI_WPR (1 << MVI_V_WPR) /* wr viol */
#define MVI_BPG 0020000 /* base page viol */
#define MVI_PRV 0010000 /* priv viol */
#define MVI_MEB 0000200 /* me bus enb @ viol */
#define MVI_MEM 0000100 /* mem enb @ viol */
#define MVI_UMP 0000040 /* usr map @ viol */
#define MVI_PAG 0000037 /* pag sel */
#define MVI_BPG 0020000u /* base page viol */
#define MVI_PRV 0010000u /* priv viol */
#define MVI_MEB 0000200u /* me bus enb @ viol */
#define MVI_MEM 0000100u /* mem enb @ viol */
#define MVI_UMP 0000040u /* usr map @ viol */
#define MVI_PAG 0000037u /* pag sel */
/* CPU registers */
#define AR ABREG[0] /* A = reg 0 */
#define BR ABREG[1] /* B = reg 1 */
#define AR ABREG [0] /* A = reg 0 */
#define BR ABREG [1] /* B = reg 1 */
extern HP_WORD ABREG [2]; /* A/B regs (use AR/BR) */
extern HP_WORD PR; /* P register */
extern HP_WORD SR; /* S register */
extern HP_WORD MR; /* M register */
extern HP_WORD TR; /* T register */
extern HP_WORD XR; /* X register */
extern HP_WORD YR; /* Y register */
extern uint32 E; /* E register */
extern uint32 O; /* O register */
extern HP_WORD IR; /* Instruction Register */
extern HP_WORD CIR; /* Central Interrupt Register */
extern uint16 ABREG[2]; /* A/B regs (use AR/BR) */
extern uint32 PR; /* P register */
extern uint32 SR; /* S register */
extern uint32 MR; /* M register */
extern uint32 TR; /* T register */
extern uint32 XR; /* X register */
extern uint32 YR; /* Y register */
extern uint32 E; /* E register */
extern uint32 O; /* O register */
/* CPU state */
extern uint32 err_PC;
extern HP_WORD err_PC;
extern uint32 dms_enb;
extern uint32 dms_ump;
extern uint32 dms_sr;
extern uint32 dms_vr;
extern HP_WORD dms_sr;
extern FLIP_FLOP mp_control;
extern uint32 mp_fence;
extern uint32 mp_viol;
extern HP_WORD mp_fence;
extern HP_WORD mp_viol;
extern FLIP_FLOP mp_mevff;
extern uint32 iop_sp;
extern HP_WORD iop_sp;
extern t_bool ion_defer;
extern uint32 intaddr;
extern uint16 pcq [PCQ_SIZE];
extern uint32 pcq_p;
extern uint32 stop_inst;
extern UNIT cpu_unit;
extern DEVICE cpu_dev;
extern REG cpu_reg [];
extern jmp_buf save_env;
extern t_bool mp_mem_changed;
extern t_stat cpu_ss_unimpl; /* status return for unimplemented instruction execution */
extern t_stat cpu_ss_undef; /* status return for undefined instruction execution */
extern t_stat cpu_ss_unsc; /* status return for I/O to an unassigned select code */
extern t_stat cpu_ss_ioerr; /* status return for an unreported I/O error */
extern t_stat cpu_ss_indir; /* status return for indirect loop execution */
extern t_stat cpu_ss_inhibit; /* simulation stop inhibition mask */
extern UNIT *cpu_ioerr_uptr; /* pointer to a unit with an unreported I/O error */
extern uint32 cpu_configuration; /* the current CPU option set and model */
extern uint32 cpu_speed; /* the CPU speed, expressed as a multiplier of a real machine */
/* CPU functions */
/* CPU global SCP support routines declared in scp.h
#define MP_ABORT(va) longjmp (save_env, (va))
extern t_stat sim_instr (void);
*/
extern t_stat resolve (uint32 MA, uint32 *addr, uint32 irq);
extern uint16 ReadPW (uint32 pa);
extern uint8 ReadB (uint32 va);
extern uint8 ReadBA (uint32 va);
extern uint16 ReadW (uint32 va);
extern uint16 ReadWA (uint32 va);
extern uint16 ReadIO (uint32 va, uint32 map);
extern void WritePW (uint32 pa, uint32 dat);
extern void WriteB (uint32 va, uint32 dat);
extern void WriteBA (uint32 va, uint32 dat);
extern void WriteW (uint32 va, uint32 dat);
extern void WriteWA (uint32 va, uint32 dat);
extern void WriteIO (uint32 va, uint32 dat, uint32 map);
extern t_stat iogrp (uint32 ir, uint32 iotrap);
extern uint32 calc_int (void);
extern t_bool calc_defer (void);
extern void mp_dms_jmp (uint32 va, uint32 plb);
extern uint16 dms_rmap (uint32 mapi);
extern void dms_wmap (uint32 mapi, uint32 dat);
extern void dms_viol (uint32 va, uint32 st);
extern uint32 dms_upd_vr (uint32 va);
extern uint32 dms_upd_sr (void);
#endif
/* CPU global SCP support routines */
extern void cpu_post_cmd (t_bool from_scp);
/* CPU global utility routines */
extern void cpu_ibl (const BOOT_ROM rom, int32 dev, HP_WORD sr_clear, HP_WORD sr_set);
extern t_stat cpu_iog (HP_WORD IR, t_bool iotrap);
extern uint32 calc_int (void);
extern t_stat resolve (HP_WORD MA, HP_WORD *address, uint32 irq);
/* Memory global utility routines */
extern HP_WORD mem_read (DEVICE *dptr, ACCESS_CLASS classification, HP_WORD address);
extern void mem_write (DEVICE *dptr, ACCESS_CLASS classification, HP_WORD address, HP_WORD value);
extern uint8 mem_read_byte (DEVICE *dptr, ACCESS_CLASS classification, HP_WORD byte_address);
extern void mem_write_byte (DEVICE *dptr, ACCESS_CLASS classification, HP_WORD byte_address, uint8 value);
extern HP_WORD mem_fast_read (HP_WORD address, uint32 map);
extern HP_WORD mem_examine (uint32 address);
extern void mem_deposit (uint32 address, HP_WORD value);
/* Memory Expansion Unit global utility routines */
extern uint16 dms_rmap (uint32 mapi);
extern void dms_wmap (uint32 mapi, uint32 dat);
extern void dms_viol (uint32 va, HP_WORD st);
extern HP_WORD dms_upd_vr (uint32 va);
extern HP_WORD dms_upd_sr (void);
/* Memory Protect global utility routines */
extern void mp_dms_jmp (uint32 va, uint32 plb);

View File

@@ -1,6 +1,6 @@
/* hp2100_cpu0.c: HP 1000 user microcode and unimplemented instruction set stubs
Copyright (c) 2006-2012, J. David Bryan
Copyright (c) 2006-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 @@
CPU0 User microcode and unimplemented firmware options
01-Aug-17 JDB Changed .FLUN and self-tests to test for unimplemented stops
09-May-12 JDB Separated assignments from conditional expressions
04-Nov-10 JDB Removed DS note regarding PIF card (is now implemented)
18-Sep-08 JDB .FLUN and self-tests for VIS and SIGNAL are NOP if not present
@@ -138,8 +139,8 @@ if (op_ds [entry] != OP_N) {
switch (entry) { /* decode IR<3:0> */
default: /* others undefined */
reason = stop_inst;
default: /* others unimplemented */
reason = STOP (cpu_ss_unimpl);
}
return reason;
@@ -151,7 +152,7 @@ return reason;
All UIG instructions unclaimed by installed firmware options are directed
here. User- or site-specific firmware may be simulated by dispatching to the
appropriate simulator routine. Unimplemented instructions should return
"stop_inst" to cause a simulator stop if enabled.
"STOP (cpu_ss_unimpl)" to cause a simulator stop if enabled.
Implementation notes:
@@ -182,15 +183,7 @@ t_stat cpu_user (uint32 IR, uint32 intrq)
t_stat reason = SCPE_OK;
if (UNIT_CPU_TYPE == UNIT_TYPE_211X) /* 2116/15/14 CPU? */
return stop_inst; /* user microprograms not supported */
switch (IR) {
case 0105226: /* firmware detection: FFP .FLUN */
case 0105355: /* firmware detection: RTE-6/VM OS self-test */
case 0105477: /* firmware detection: VIS self-test */
case 0105617: /* firmware detection: SIGNAL/1000 self-test */
return SCPE_OK; /* execute as NOP */
}
return STOP (cpu_ss_unimpl); /* user microprograms not supported */
switch ((IR >> 4) & 037) { /* decode IR<8:4> */
@@ -212,8 +205,8 @@ switch ((IR >> 4) & 037) { /* decode IR<8:4> */
/* case 0nn: ** other cases as needed */
/* return cpu_user_nn (IR, intrq); ** uncomment to handle instruction */
default: /* others undefined */
reason = stop_inst;
default: /* others unimplemented */
reason = STOP (cpu_ss_unimpl);
}
return reason;
@@ -223,8 +216,8 @@ return reason;
/* Example user microprogram simulator.
User- or site-specific firmware may be simulated by writing the appropriate
code below. Unimplemented instructions should return "stop_inst" to cause a
simulator stop if enabled.
code below. Unimplemented instructions should return "STOP (cpu_ss_unimpl)"
to cause a simulator stop if enabled.
For information on the operand patterns used in the "op_user" array, see the
comments preceding the "cpu_ops" routine in "hp2100_cpu1.c" and the "operand
@@ -263,8 +256,8 @@ switch (entry) { /* decode IR<4:0> */
/* case 0nn: ** other cases as needed */
/* break; ** uncomment to handle instruction */
default: /* others undefined */
reason = stop_inst;
default: /* others unimplemented */
reason = STOP (cpu_ss_unimpl);
}
return reason;

View File

@@ -26,8 +26,13 @@
CPU1 Extended arithmetic and optional microcode dispatchers
01-Aug-17 JDB Changed TIMER and RRR 16 to test for undefined stops
07-Jul-17 JDB Changed "iotrap" from uint32 to t_bool
26-Jun-17 JDB Replaced SEXT with SEXT16
22-Apr-17 JDB Improved the EAU shift/rotate instructions
21-Mar-17 JDB Fixed UIG 1 comment regarding 2000 IOP and F-Series
31-Jan-17 JDB Added fmt_ab to print A/B-register error codes
30-Jan-17 JDB Removed fprint_ops, fprint_regs (now redundant)
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
@@ -121,16 +126,18 @@
The design of the 1000 microinstruction set was such that executing an
instruction for which no microcode was present (e.g., executing a FFP
instruction when the FFP firmware was not installed) resulted in a NOP.
Under simulation, such execution causes an undefined instruction stop if
"stop_inst" is non-zero and a NOP otherwise.
Under simulation, such execution causes an unimplemented instruction stop if
"STOP (cpu_ss_unimpl)" is non-zero and a no-operation otherwise.
*/
#include "hp2100_defs.h"
#include "hp2100_cpu.h"
#include "hp2100_cpu1.h"
/* EAU
The Extended Arithmetic Unit (EAU) adds ten instructions with double-word
@@ -175,13 +182,15 @@
EXECUTE (100120), is also described but was never implemented, and the
E/F-series microcode execute a NOP for this instruction code.
If the EAU is not installed in a 2115 or 2116, EAU instructions execute as
NOPs or cause unimplemented instruction stops if enabled.
Implementation 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.
1. Under simulation, TIMER and DIAG cause undefined instruction stops if the
CPU is not an E/F-Series. Note that TIMER is intentionally executed by
several HP programs to differentiate between M- and E/F-series machines.
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
@@ -189,9 +198,9 @@
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.
3. The RRR 16 instruction is intentionally executed by the diagnostic
configurator on the 2114, which does not have an EAU, 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.
@@ -215,11 +224,8 @@ OPS op;
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? */
return SCPE_OK; /* allowed as NOP */
else
return stop_inst; /* fail */
if ((cpu_unit.flags & UNIT_EAU) == 0) /* if the EAU is not installed */
return STOP (cpu_ss_unimpl); /* then the instructions execute as NOPs */
if (IR & 017) /* if the shift count is 1-15 */
shift = IR & 017; /* then use it verbatim */
@@ -232,10 +238,10 @@ switch ((IR >> 8) & 0377) { /* decode IR<15:8> */
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 */
if (UNIT_CPU_MODEL != UNIT_1000_E /* if the CPU is not an E-series */
&& UNIT_CPU_MODEL != UNIT_1000_F) /* or an F-series */
return STOP (cpu_ss_undef); /* then the instruction is undefined */
break; /* and executes as NOP */
case 001: /* ASL 100020-100037 */
@@ -277,25 +283,31 @@ switch ((IR >> 8) & 0377) { /* decode IR<15:8> */
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_E /* if the CPU is an E-series */
|| UNIT_CPU_MODEL == UNIT_1000_F) { /* or an F-series */
BR = BR + 1 & R_MASK; /* then increment B */
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;
if (BR != 0) /* if B did not roll over */
PR = err_PC; /* then repeat the instruction */
break;
}
else { /* otherwise it's a 21xx or 1000 M-Series */
reason = STOP (cpu_ss_undef); /* and the instruction is undefined */
if (reason != SCPE_OK /* if a stop is indicated */
|| UNIT_CPU_MODEL != UNIT_1000_M) /* or the CPU is a 21xx */
break; /* then the instruction executes as NOP */
}
/* 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 = SEXT16 (AR); /* sext AR */
sop2 = SEXT16 (op[0].word); /* sext mem */
sop1 = sop1 * sop2; /* signed mpy */
BR = UPPER_WORD (sop1); /* to BR'AR */
AR = LOWER_WORD (sop1);
@@ -305,7 +317,7 @@ switch ((IR >> 8) & 0377) { /* decode IR<15:8> */
default: /* others undefined */
return stop_inst;
return STOP (cpu_ss_unimpl);
}
break;
@@ -392,7 +404,7 @@ switch ((IR >> 8) & 0377) { /* decode IR<15:8> */
default: /* others undefined */
return stop_inst;
return STOP (cpu_ss_undef);
}
break;
@@ -480,7 +492,7 @@ return reason;
user microcode dispatcher.
*/
t_stat cpu_uig_0 (uint32 IR, uint32 intrq, uint32 iotrap)
t_stat cpu_uig_0 (uint32 IR, uint32 intrq, t_bool iotrap)
{
if ((cpu_unit.flags & UNIT_IOP) && /* I/O Processor? */
(UNIT_CPU_TYPE == UNIT_TYPE_2100)) /* and 2100 CPU? */
@@ -621,10 +633,10 @@ return cpu_user (IR, intrq); /* try user microcode */
user microcode dispatcher.
*/
t_stat cpu_uig_1 (uint32 IR, uint32 intrq, uint32 iotrap)
t_stat cpu_uig_1 (uint32 IR, uint32 intrq, t_bool iotrap)
{
if (UNIT_CPU_TYPE != UNIT_TYPE_1000) /* 1000 execution? */
return stop_inst; /* no, so trap */
if (UNIT_CPU_TYPE != UNIT_TYPE_1000) /* if the CPU is not a 1000 */
return STOP (cpu_ss_unimpl); /* the the instruction is unimplemented */
switch ((IR >> 4) & 017) { /* decode IR<7:4> */
@@ -680,7 +692,7 @@ return cpu_user (IR, intrq); /* try user microcode */
/* Read a multiple-precision operand value. */
OP ReadOp (uint32 va, OPSIZE precision)
OP ReadOp (HP_WORD va, OPSIZE precision)
{
OP operand;
uint32 i;
@@ -702,7 +714,7 @@ return operand;
/* Write a multiple-precision operand value. */
void WriteOp (uint32 va, OP operand, OPSIZE precision)
void WriteOp (HP_WORD va, OP operand, OPSIZE precision)
{
uint32 i;
@@ -810,19 +822,29 @@ return;
An operand pattern consists of one or more operand encodings, corresponding
to the operands required by a given instruction. Values are returned in
sequence to the operand array.
Implementation notes:
1. The reads of address operand words that follow an instruction (e.g., the
DEFs above) are classified as instruction fetches. The reads of the
operands themselves are classified as data accesses.
*/
t_stat cpu_ops (OP_PAT pattern, OPS op, uint32 irq)
{
t_stat reason = SCPE_OK;
OP_PAT flags;
uint32 i, MA;
OP_PAT flags;
uint32 i;
HP_WORD MA, address;
t_stat reason = SCPE_OK;
for (i = 0; i < OP_N_F; i++) {
flags = pattern & OP_M_FLAGS; /* get operand pattern */
if (flags >= OP_ADR) { /* address operand? */
reason = resolve (ReadW (PR), &MA, irq); /* resolve indirects */
address = ReadF (PR); /* get the pointer */
reason = resolve (address, &MA, irq); /* resolve indirects */
if (reason != SCPE_OK) /* resolution failed? */
return reason;
}
@@ -892,117 +914,33 @@ return reason;
}
/* Print operands to the debug device.
/* Format an error code in the A and B registers.
The values of an operand array are printed to the debug device. The types of
the operands are specified by an operand pattern. Typically, the operand
pattern is the same one that was used to fill the array originally.
This routine conditionally formats the contents of the A and B registers into
an error message. If the supplied "success" flag is 0, the A and B registers
contain a four-character error code (e.g., "EM82"), with the leading
characters in the B register. The characters are moved into the error
message, and a pointer to the message is returned. If "success" is non-zero,
then a pointer to the message reporting normal execution is returned.
The routine is typically called from an instructio executor during operand
tracing.
*/
void fprint_ops (OP_PAT pattern, OPS op)
const char *fmt_ab (t_bool success)
{
OP_PAT flags;
uint32 i;
static const char good [] = "normal";
static char error [] = "error ....";
for (i = 0; i < OP_N_F; i++) {
flags = pattern & OP_M_FLAGS; /* get operand pattern */
if (success) /* if the instruction succeeded */
return good; /* then report a normal completion */
switch (flags) {
case OP_NUL: /* null operand */
return; /* no more, so quit */
else { /* otherwise */
error [6] = UPPER_BYTE (BR); /* format the */
error [7] = LOWER_BYTE (BR); /* error code */
error [8] = UPPER_BYTE (AR); /* into the */
error [9] = LOWER_BYTE (AR); /* error message */
case OP_IAR: /* int in A */
case OP_CON: /* inline constant operand */
case OP_VAR: /* inline variable operand */
case OP_ADR: /* inline address operand */
case OP_ADK: /* address of int constant */
fprintf (sim_deb,
", op[%d] = %06o",
i, op[i].word);
break;
case OP_JAB: /* dbl-int in A/B */
case OP_ADD: /* address of dbl-int constant */
fprintf (sim_deb,
", op[%d] = %011o",
i, op[i].dword);
break;
case OP_FAB: /* 2-word FP in A/B */
case OP_ADF: /* address of 2-word FP const */
fprintf (sim_deb,
", op[%d] = (%06o, %06o)",
i, op[i].fpk[0], op[i].fpk[1]);
break;
case OP_ADX: /* address of 3-word FP const */
fprintf (sim_deb,
", op[%d] = (%06o, %06o, %06o)",
i, op[i].fpk[0], op[i].fpk[1],
op[i].fpk[2]);
break;
case OP_ADT: /* address of 4-word FP const */
fprintf (sim_deb,
", op[%d] = (%06o, %06o, %06o, %06o)",
i, op[i].fpk[0], op[i].fpk[1],
op[i].fpk[2], op[i].fpk[3]);
break;
case OP_ADE: /* address of 5-word FP const */
fprintf (sim_deb,
", op[%d] = (%06o, %06o, %06o, %06o, %06o)",
i, op[i].fpk[0], op[i].fpk[1],
op[i].fpk[2], op[i].fpk[3], op[i].fpk[4]);
break;
default:
fprintf (sim_deb, "UNKNOWN OPERAND TYPE"); /* not implemented */
}
pattern = pattern >> OP_N_FLAGS; /* move next pattern into place */
return error; /* report an abnormal completion */
}
}
/* Print CPU registers to the debug device.
One or more CPU registers may be printed to the debug output device, which
must be valid before calling.
*/
void fprint_regs (char *caption, uint32 regs, uint32 base)
{
static uint32 ARX, BRX, PRL; /* static so addresses are constant */
static const char *reg_names[] = { "CIR", "A", "B", "E", "X", "Y", "O", "P", "return" };
static const uint32 *reg_ptrs[] = { &intaddr, &ARX, &BRX, &E, &XR, &YR, &O, &PR, &PRL };
static const char *formats[] = { "%02o", "%06o", "%06o", "%01o", "%06o", "%06o", "%01o", "%06o", "P+%d" };
static char format[20] = " %s = "; /* base format string */
static const int eos = 6; /* length of base format string */
uint32 i;
t_bool first = TRUE; /* first-time through flag */
ARX = AR; /* copy 16-bit value to static variable */
BRX = BR; /* copy 16-bit value to static variable */
PRL = PR - base; /* compute value in static variable */
for (i = 0; i < REG_COUNT; i++) {
if (regs & 1) { /* register requested? */
if (first) /* first time? */
fputs (caption, sim_deb); /* print caption */
else
fputc (',', sim_deb); /* print separator */
strcpy (&format[eos], formats[i]); /* copy format specifier */
fprintf (sim_deb, format, reg_names[i], *reg_ptrs[i]);
first = FALSE;
}
regs = regs >> 1; /* align next register flag */
}
return;
}

View File

@@ -1,6 +1,6 @@
/* hp2100_cpu1.h: HP 2100/1000 firmware dispatcher definitions
/* hp2100_cpu1.h: HP 2100/1000 firmware dispatcher declarations
Copyright (c) 2006-2013, J. David Bryan
Copyright (c) 2006-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 +23,10 @@
be used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from the author.
07-Jul-17 JDB Changed "iotrap" from uint32 to t_bool
15-Feb-17 JDB Deleted unneeded guard macro definition
26-Jan-17 JDB Removed debug parameters from cpu_ema_* routines
17-Jan-17 JDB Removed register print encoding constants (now redundant)
18-Mar-13 JDB Added externs for microcode helper functions
14-Mar-13 MP Changed guard macro name to avoid reserved namespace
11-Sep-08 JDB Moved microcode function prototypes here
@@ -35,23 +39,6 @@
26-Sep-06 JDB Split from hp2100_cpu1.c
*/
#ifndef HP2100_CPU1_H_
#define HP2100_CPU1_H_
/* Register print encoding */
#define REG_COUNT 9 /* count of print flags */
#define REG_CIR (1 << 0) /* print central interrupt register */
#define REG_A (1 << 1) /* print A register */
#define REG_B (1 << 2) /* print B register */
#define REG_E (1 << 3) /* print E register */
#define REG_X (1 << 4) /* print X register */
#define REG_Y (1 << 5) /* print Y register */
#define REG_O (1 << 6) /* print O register */
#define REG_P (1 << 7) /* print P register */
#define REG_P_REL (1 << 8) /* print P register as relative */
/* Operand processing encoding */
@@ -246,7 +233,7 @@ typedef enum { in_s, in_d, fp_f, fp_x, fp_t, fp_e, fp_a } OPSIZE;
Actual value will use two, three, four, or five words, as needed.
*/
typedef uint16 FPK[5];
typedef HP_WORD FPK [5];
/* Operand processing types.
@@ -259,9 +246,9 @@ typedef uint16 FPK[5];
*/
typedef union { /* general operand */
FPK fpk; /* floating-point value */
uint16 word; /* 16-bit integer */
uint32 dword; /* 32-bit integer */
FPK fpk; /* floating-point value */
HP_WORD word; /* 16-bit integer */
uint32 dword; /* 32-bit integer */
} OP;
typedef OP OPS[OP_N_F]; /* operand array */
@@ -276,8 +263,8 @@ extern t_stat cpu_user (uint32 IR, uint32 intrq); /* [0] User
extern t_stat cpu_user_20 (uint32 IR, uint32 intrq); /* [0] Module 20 user microprograms stub */
extern t_stat cpu_eau (uint32 IR, uint32 intrq); /* [1] EAU group simulator */
extern t_stat cpu_uig_0 (uint32 IR, uint32 intrq, uint32 iotrap); /* [1] UIG group 0 dispatcher */
extern t_stat cpu_uig_1 (uint32 IR, uint32 intrq, uint32 iotrap); /* [1] UIG group 1 dispatcher */
extern t_stat cpu_uig_0 (uint32 IR, uint32 intrq, t_bool iotrap); /* [1] UIG group 0 dispatcher */
extern t_stat cpu_uig_1 (uint32 IR, uint32 intrq, t_bool iotrap); /* [1] UIG group 1 dispatcher */
#if !defined (HAVE_INT64) /* int64 support unavailable */
extern t_stat cpu_fp (uint32 IR, uint32 intrq); /* [2] Firmware Floating Point */
@@ -297,7 +284,7 @@ extern t_stat cpu_sis (uint32 IR, uint32 intrq); /* [4] Scien
extern t_stat cpu_rte_vma (uint32 IR, uint32 intrq); /* [5] RTE-6 VMA */
extern t_stat cpu_rte_ema (uint32 IR, uint32 intrq); /* [5] RTE-IV EMA */
extern t_stat cpu_rte_os (uint32 IR, uint32 intrq, uint32 iotrap); /* [6] RTE-6 OS */
extern t_stat cpu_rte_os (uint32 IR, uint32 intrq, t_bool iotrap); /* [6] RTE-6 OS */
#if defined (HAVE_INT64) /* int64 support available */
extern t_stat cpu_vis (uint32 IR, uint32 intrq); /* [7] Vector Instruction Set */
@@ -307,17 +294,14 @@ extern t_stat cpu_signal (uint32 IR, uint32 intrq); /* [7] SIGNA
/* Microcode helper functions */
extern OP ReadOp (uint32 va, OPSIZE precision); /* generalized operand read */
extern void WriteOp (uint32 va, OP operand, OPSIZE precision); /* generalized operand write */
extern t_stat cpu_ops (OP_PAT pattern, OPS op, uint32 irq); /* operand processor */
extern OP ReadOp (HP_WORD va, OPSIZE precision); /* generalized operand read */
extern void WriteOp (HP_WORD va, OP operand, OPSIZE precision); /* generalized operand write */
extern t_stat cpu_ops (OP_PAT pattern, OPS op, uint32 irq); /* operand processor */
extern void fprint_ops (OP_PAT pattern, OPS op); /* debug print operands */
extern void fprint_regs (char *caption, uint32 regs, uint32 base); /* debug print CPU registers */
extern const char *fmt_ab (t_bool success); /* format an error code in the A/B registers */
/* implemented in hp2100_cpu5.c (RTE-IV EMA functions) */
extern t_stat cpu_ema_eres (uint32 *rtn, uint32 dtbl, uint32 atbl, t_bool debug);
extern t_stat cpu_ema_eseg (uint32 *rtn, uint32 ir, uint32 tbl, t_bool debug);
extern t_stat cpu_ema_vset (uint32 *rtn, OPS op, t_bool debug);
#endif
extern t_stat cpu_ema_eres (HP_WORD *rtn, uint32 dtbl, uint32 atbl);
extern t_stat cpu_ema_eseg (HP_WORD *rtn, uint32 ir, uint32 tbl);
extern t_stat cpu_ema_vset (HP_WORD *rtn, OPS op);

View File

@@ -1,31 +1,36 @@
/* hp2100_cpu2.c: HP 2100/1000 FP/DMS/EIG/IOP instructions
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.
CPU2 Floating-point, dynamic mapping, extended, and I/O processor
instructions
10-Jul-17 JDB Renamed the global routine "iogrp" to "cpu_iog"
26-Jun-17 JDB Replaced SEXT with SEXT16
22-Mar-17 JDB Corrected comments regarding IR bit 11 selecting A/B
25-Jan-17 JDB Set mp_mem_changed whenever MEM registers are changed
05-Aug-16 JDB Renamed the P register from "PC" to "PR"
24-Dec-14 JDB Added casts for explicit downward conversions
09-May-12 JDB Separated assignments from conditional expressions
@@ -202,12 +207,13 @@ return reason;
10x716 [nop] [nop] 10x736 UJP UJP
10x717 [nop] [nop] 10x737 UJS UJS
Instructions that use IR bit 9 to select the A or B register are designated
Instructions that use IR bit 11 to select the A or B register are designated
with a * above (e.g., 101710 is SYA, and 105710 is SYB). For those that do
not use this feature, either the 101xxx or 105xxx code will execute the
corresponding instruction, although the 105xxx form is the documented
instruction code.
Implementation notes:
1. Instruction code 10x700 will execute the XMM instruction, although 10x720
@@ -221,8 +227,8 @@ return reason;
- load map and CTL5 set (XMM, XMS, XM*, SY*, US*, PA*, PB*)
- load state or fence and UMAP set (JRS, DJP, DJS, SJP, SJS, UJP, UJS, LF*)
4. The 1000 manual is incorrect in stating that M*I, M*W, XS* are
privileged.
4. DM (write) violations for the use of the MBI, MWI, MBW, MWW, XSA, and XSB
instructions in protected mode are generated by the mem_write routine.
5. The protected memory lower bound for the DJP, SJP, UJP, and JRS
instructions is 2.
@@ -243,8 +249,9 @@ t_stat cpu_dms (uint32 IR, uint32 intrq)
{
t_stat reason = SCPE_OK;
OPS op;
uint32 entry, absel;
uint32 i, t, mapi, mapj;
uint8 byte;
uint32 entry, absel, i, mapi, mapj;
HP_WORD t;
absel = (IR & I_AB)? 1: 0; /* get A/B select */
entry = IR & 037; /* mask to entry point */
@@ -272,8 +279,8 @@ switch (entry) { /* decode IR<3:0> */
AR = AR & ~1; /* force A, B even */
BR = BR & ~1;
while (XR != 0) { /* loop */
t = ReadB (AR); /* read curr */
WriteBA (BR, t); /* write alt */
byte = ReadB (AR); /* read curr */
WriteBA (BR, byte); /* write alt */
AR = (AR + 1) & DMASK; /* incr ptrs */
BR = (BR + 1) & DMASK;
XR = (XR - 1) & DMASK;
@@ -288,8 +295,8 @@ switch (entry) { /* decode IR<3:0> */
AR = AR & ~1; /* force A, B even */
BR = BR & ~1;
while (XR != 0) { /* loop */
t = ReadBA (AR); /* read alt */
WriteB (BR, t); /* write curr */
byte = ReadBA (AR); /* read alt */
WriteB (BR, byte); /* write curr */
AR = (AR + 1) & DMASK; /* incr ptrs */
BR = (BR + 1) & DMASK;
XR = (XR - 1) & DMASK;
@@ -304,8 +311,8 @@ switch (entry) { /* decode IR<3:0> */
AR = AR & ~1; /* force A, B even */
BR = BR & ~1;
while (XR != 0) { /* loop */
t = ReadBA (AR); /* read alt */
WriteBA (BR, t); /* write alt */
byte = ReadBA (AR); /* read alt */
WriteBA (BR, byte); /* write alt */
AR = (AR + 1) & DMASK; /* incr ptrs */
BR = (BR + 1) & DMASK;
XR = (XR - 1) & DMASK;
@@ -391,10 +398,11 @@ switch (entry) { /* decode IR<3:0> */
dms_enb = 1;
if (op[0].word & 0040000) dms_ump = UMAP; /* set/clr usr */
}
mp_mem_changed = TRUE; /* set the MP/MEM registers changed flag */
mp_dms_jmp (op[1].word, 2); /* mpck jmp target */
PCQ_ENTRY; /* save old P */
PR = op[1].word; /* jump */
ion_defer = 1; /* defer intr */
ion_defer = TRUE; /* defer intr */
break;
/* DMS module 2 */
@@ -467,6 +475,8 @@ switch (entry) { /* decode IR<3:0> */
if (dms_ump) dms_viol (err_PC, MVI_PRV); /* priv viol if prot */
dms_sr = (dms_sr & ~(MST_FLT | MST_FENCE)) |
(ABREG[absel] & (MST_FLT | MST_FENCE));
mp_mem_changed = TRUE; /* set the MP/MEM registers changed flag */
break;
case 030: /* RSA, RSB 10x730 (OP_N) */
@@ -484,7 +494,7 @@ switch (entry) { /* decode IR<3:0> */
mp_dms_jmp (op[0].word, 2); /* validate jump addr */
PCQ_ENTRY; /* save curr P */
PR = op[0].word; /* new P */
ion_defer = 1;
ion_defer = TRUE; /* defer interrupts */
break;
case 033: /* DJS 105733 (OP_A) */
@@ -494,7 +504,7 @@ switch (entry) { /* decode IR<3:0> */
PR = (op[0].word + 1) & VAMASK; /* new P */
dms_enb = 0; /* disable map */
dms_ump = SMAP;
ion_defer = 1; /* defer intr */
ion_defer = TRUE; /* defer intr */
break;
case 034: /* SJP 105734 (OP_A) */
@@ -504,7 +514,7 @@ switch (entry) { /* decode IR<3:0> */
mp_dms_jmp (op[0].word, 2); /* validate jump addr */
PCQ_ENTRY; /* save curr P */
PR = op[0].word; /* jump */
ion_defer = 1; /* defer intr */
ion_defer = TRUE; /* defer intr */
break;
case 035: /* SJS 105735 (OP_A) */
@@ -515,7 +525,7 @@ switch (entry) { /* decode IR<3:0> */
dms_enb = 1; /* enable system */
dms_ump = SMAP;
WriteW (op[0].word, t); /* store ret addr */
ion_defer = 1; /* defer intr */
ion_defer = TRUE; /* defer intr */
break;
case 036: /* UJP 105736 (OP_A) */
@@ -525,7 +535,7 @@ switch (entry) { /* decode IR<3:0> */
mp_dms_jmp (op[0].word, 2); /* validate jump addr */
PCQ_ENTRY; /* save curr P */
PR = op[0].word; /* jump */
ion_defer = 1; /* defer intr */
ion_defer = TRUE; /* defer intr */
break;
case 037: /* UJS 105737 (OP_A) */
@@ -536,7 +546,7 @@ switch (entry) { /* decode IR<3:0> */
dms_enb = 1; /* enable user */
dms_ump = UMAP;
WriteW (op[0].word, t); /* store ret addr */
ion_defer = 1; /* defer intr */
ion_defer = TRUE; /* defer intr */
break;
default: /* others NOP */
@@ -581,7 +591,7 @@ return reason;
10x756 ADY 10x776 CMW
10x757 X*Y 10x777 MVW
Instructions that use IR bit 9 to select the A or B register are designated
Instructions that use IR bit 11 to select the A or B register are designated
with a * above (e.g., 101740 is SAX, and 105740 is SBX). For those that do
not use this feature, either the 101xxx or 105xxx code will execute the
corresponding instruction, although the 105xxx form is the documented
@@ -611,8 +621,9 @@ t_stat cpu_eig (uint32 IR, uint32 intrq)
{
t_stat reason = SCPE_OK;
OPS op;
uint32 entry, absel;
uint32 t, v1, v2, wc;
uint8 byte, b1, b2;
uint32 entry, absel, sum;
HP_WORD t, v1, v2, wc;
int32 sop1, sop2;
absel = (IR & I_AB)? 1: 0; /* get A/B select */
@@ -656,10 +667,10 @@ switch (entry) { /* decode IR<4:0> */
break;
case 006: /* ADX 105746 (OP_K) */
t = XR + op[0].word; /* add to XR */
if (t > DMASK) E = 1; /* set E, O */
if (((~XR ^ op[0].word) & (XR ^ t)) & SIGN) O = 1;
XR = t & DMASK;
sum = XR + op[0].word; /* add to XR */
if (sum > DMASK) E = 1; /* set E, O */
if (((~XR ^ op[0].word) & (XR ^ sum)) & SIGN) O = 1;
XR = sum & DMASK;
break;
case 007: /* XAX, XBX 10x747 (OP_N) */
@@ -695,10 +706,10 @@ switch (entry) { /* decode IR<4:0> */
break;
case 016: /* ADY 105756 (OP_K) */
t = YR + op[0].word; /* add to YR */
if (t > DMASK) E = 1; /* set E, O */
if (((~YR ^ op[0].word) & (YR ^ t)) & SIGN) O = 1;
YR = t & DMASK;
sum = YR + op[0].word; /* add to YR */
if (sum > DMASK) E = 1; /* set E, O */
if (((~YR ^ op[0].word) & (YR ^ sum)) & SIGN) O = 1;
YR = sum & DMASK;
break;
case 017: /* XAY, XBY 10x757 (OP_N) */
@@ -732,7 +743,7 @@ switch (entry) { /* decode IR<4:0> */
break;
case 024: /* SBT 105764 (OP_N) */
WriteB (BR, AR); /* store byte */
WriteB (BR, LOWER_BYTE (AR)); /* store byte */
BR = (BR + 1) & DMASK; /* incr ptr */
break;
@@ -744,8 +755,8 @@ switch (entry) { /* decode IR<4:0> */
break; /* < 0 is NOP for 2100 IOP */
while (wc != 0) { /* while count */
WriteW (op[1].word, wc); /* for MP abort */
t = ReadB (AR); /* move byte */
WriteB (BR, t);
byte = ReadB (AR); /* move byte */
WriteB (BR, byte);
AR = (AR + 1) & DMASK; /* incr src */
BR = (BR + 1) & DMASK; /* incr dst */
wc = (wc - 1) & DMASK; /* decr cnt */
@@ -762,10 +773,10 @@ switch (entry) { /* decode IR<4:0> */
if (wc == 0) wc = op[0].word; /* none? get initiation count */
while (wc != 0) { /* while count */
WriteW (op[1].word, wc); /* for MP abort */
v1 = ReadB (AR); /* get src1 */
v2 = ReadB (BR); /* get src2 */
if (v1 != v2) { /* compare */
PR = (PR + 1 + (v1 > v2)) & VAMASK;
b1 = ReadB (AR); /* get src1 */
b2 = ReadB (BR); /* get src2 */
if (b1 != b2) { /* compare */
PR = (PR + 1 + (b1 > b2)) & VAMASK;
BR = (BR + wc) & DMASK; /* update BR */
wc = 0; /* clr interim */
break;
@@ -782,13 +793,13 @@ switch (entry) { /* decode IR<4:0> */
break;
case 027: /* SFB 105767 (OP_N) */
v1 = AR & 0377; /* test byte */
v2 = (AR >> 8) & 0377; /* term byte */
b1 = LOWER_BYTE (AR); /* test byte */
b2 = UPPER_BYTE (AR); /* term byte */
for (;;) { /* scan */
t = ReadB (BR); /* read byte */
if (t == v1) break; /* test match? */
byte = ReadB (BR); /* read byte */
if (byte == b1) break; /* test match? */
BR = (BR + 1) & DMASK;
if (t == v2) { /* term match? */
if (byte == b2) { /* term match? */
PR = (PR + 1) & VAMASK;
break;
}
@@ -838,8 +849,8 @@ switch (entry) { /* decode IR<4:0> */
WriteW (op[1].word, wc); /* for abort */
v1 = ReadW (AR & VAMASK); /* first op */
v2 = ReadW (BR & VAMASK); /* second op */
sop1 = (int32) SEXT (v1); /* signed */
sop2 = (int32) SEXT (v2);
sop1 = SEXT16 (v1); /* signed */
sop2 = SEXT16 (v2);
if (sop1 != sop2) { /* compare */
PR = (PR + 1 + (sop1 > sop2)) & VAMASK;
BR = (BR + wc) & DMASK; /* update BR */
@@ -954,8 +965,9 @@ t_stat cpu_iop (uint32 IR, uint32 intrq)
{
t_stat reason = SCPE_OK;
OPS op;
uint32 entry;
uint32 hp, tp, i, t, wc, MA;
uint8 byte;
uint32 entry, i;
HP_WORD hp, tp, t, wc, MA;
if (UNIT_CPU_TYPE == UNIT_TYPE_2100) { /* 2100 IOP? */
if ((IR >= 0105020) && (IR <= 0105057)) /* remap LAI */
@@ -982,7 +994,7 @@ if (UNIT_CPU_TYPE == UNIT_TYPE_2100) { /* 2100 IOP? */
case 0105362: IR = 0105474; break; /* SAVE */
default: /* all others invalid */
return stop_inst;
return STOP (cpu_ss_unimpl);
}
}
}
@@ -996,7 +1008,7 @@ if (entry <= 037) { /* LAI/SAI 10x400-437 */
return reason;
}
else if (entry <= 057) /* IR = 10x440-457? */
return stop_inst; /* not part of IOP */
return STOP (cpu_ss_unimpl); /* not part of IOP */
entry = entry - 060; /* offset 10x460-477 */
@@ -1073,8 +1085,8 @@ switch (entry) { /* decode IR<5:0> */
if (wc & SIGN) break; /* cnt < 0? */
while (wc != 0) { /* loop */
MA = (AR + AR + ReadB (BR)) & VAMASK;
t = ReadB (MA); /* xlate */
WriteB (BR, t); /* store char */
byte = ReadB (MA); /* xlate */
WriteB (BR, byte); /* store char */
BR = (BR + 1) & DMASK; /* incr ptr */
wc = (wc - 1) & DMASK; /* decr cnt */
if (wc && intrq) { /* more and intr? */
@@ -1097,7 +1109,7 @@ switch (entry) { /* decode IR<5:0> */
case 011: /* PRFEI 105471 (OP_CVA) */
WriteW (op[1].word, 1); /* set flag */
reason = iogrp (op[0].word, 0); /* execute I/O instr */
reason = cpu_iog (op[0].word, 0); /* execute I/O instr */
op[0].word = op[2].word; /* set rtn and fall through */
case 012: /* PRFEX 105472 (OP_A) */
@@ -1108,7 +1120,7 @@ switch (entry) { /* decode IR<5:0> */
case 013: /* PRFIO 105473 (OP_CV) */
WriteW (op[1].word, 1); /* set flag */
reason = iogrp (op[0].word, 0); /* execute instr */
reason = cpu_iog (op[0].word, 0); /* execute instr */
break;
case 014: /* SAVE 105474 (OP_N) */
@@ -1116,15 +1128,15 @@ switch (entry) { /* decode IR<5:0> */
iop_sp = (iop_sp + 1) & VAMASK; /* incr stack ptr */
WriteW (iop_sp, BR); /* save B */
iop_sp = (iop_sp + 1) & VAMASK; /* incr stack ptr */
t = ((O ^ 1) << 1) | E; /* merge E and O */
t = (HP_WORD) ((O ^ 1) << 1 | E); /* merge E and O */
WriteW (iop_sp, t); /* save E and O */
iop_sp = (iop_sp + 1) & VAMASK; /* incr stack ptr */
if (UNIT_CPU_TYPE == UNIT_TYPE_2100)
mp_fence = iop_sp; /* 2100 keeps sp in MP FR */
break;
default: /* instruction undefined */
return stop_inst;
default: /* instruction unimplemented */
return STOP (cpu_ss_unimpl);
}
return reason;

View File

@@ -1,6 +1,6 @@
/* hp2100_cpu3.c: HP 2100/1000 FFP/DBI instructions
Copyright (c) 2005-2016, J. David Bryan
Copyright (c) 2005-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,8 @@
CPU3 Fast FORTRAN and Double Integer instructions
24-Aug-17 JDB op_ffp_f definition is now conditional on HAVE_INT64
27-Mar-17 JDB Improved the comments for the FFP instructions
05-Aug-16 JDB Renamed the P register from "PC" to "PR"
24-Dec-14 JDB Added casts for explicit downward conversions
09-May-12 JDB Separated assignments from conditional expressions
@@ -41,15 +43,23 @@
18-Feb-05 JDB Add 2100/21MX Fast FORTRAN Processor instructions
Primary references:
- HP 1000 M/E/F-Series Computers Technical Reference Handbook
(5955-0282, Mar-1980)
- HP 1000 M/E/F-Series Computers Engineering and Reference Documentation
(92851-90001, Mar-1981)
- Macro/1000 Reference Manual (92059-90001, Dec-1992)
- HP 1000 M/E/F-Series Computers Technical Reference Handbook
(5955-0282, March 1980)
- HP 1000 M/E/F-Series Computers Engineering and Reference Documentation
(92851-90001, March 1981)
- Macro/1000 Reference Manual
(92059-90001, December 1992)
Firmware-specific references:
- DOS/RTE Relocatable Library Reference Manual
(24998-90001, October 1981)
- Implementing the HP 2100 Fast FORTRAN Processor
(12907-90010, November 1974)
- 93585A Microcode Source
(93585-18002 Rev. 2005)
- 93585A Double Integer Instructions Installation and Reference Manual
(93585-90007, February 1984)
Additional references are listed with the associated firmware
implementations, as are the HP option model numbers pertaining to the
applicable CPUs.
*/
#include "hp2100_defs.h"
@@ -143,12 +153,14 @@
9. The protected memory lower bound for the .GOTO instruction is 2.
Additional references:
- DOS/RTE Relocatable Library Reference Manual (24998-90001, Oct-1981)
- Implementing the HP 2100 Fast FORTRAN Processor (12907-90010, Nov-1974)
10. The OP_N (none) operand pattern is used here for all double-integer
instructions. They are dispatched to the DBI handler for execution,
where the correct operands will be retrieved
*/
static const OP_PAT op_ffp_f[32] = { /* patterns for F-Series only */
#if defined (HAVE_INT64) /* int64 support available */
static const OP_PAT op_ffp_f [32] = { /* patterns for F-Series only */
OP_N, OP_AAF, OP_AX, OP_N, /* [tst] DBLE SNGL .DNG */
OP_N, OP_AA, OP_A, OP_AAF, /* .DCO .DFER .XPAK .BLE */
OP_N, OP_N, OP_N, OP_N, /* .DIN .DDE .DIS .DDS */
@@ -159,7 +171,9 @@ static const OP_PAT op_ffp_f[32] = { /* patterns for F-Series
OP_N, OP_N, OP_N, OP_N /* --- --- --- --- */
};
static const OP_PAT op_ffp_e[32] = { /* patterns for 2100/M/E-Series */
#endif /* end of int64 support */
static const OP_PAT op_ffp_e [32] = { /* patterns for 2100/M/E-Series */
OP_N, OP_AAF, OP_AX, OP_AXX, /* [nop] DBLE SNGL .XMPY */
OP_AXX, OP_AA, OP_A, OP_AAXX, /* .XDIV .DFER .XPAK XADD */
OP_AAXX, OP_AAXX, OP_AAXX, OP_AXX, /* XSUB XMPY XDIV .XADD */
@@ -175,7 +189,7 @@ t_stat cpu_ffp (uint32 IR, uint32 intrq)
OP fpop;
OPS op, op2;
uint32 entry;
uint32 j, sa, sb, sc, da, dc, ra, MA;
HP_WORD j, sa, sb, sc, da, dc, ra, MA;
int32 expon;
t_stat reason = SCPE_OK;
@@ -267,7 +281,7 @@ switch (entry) { /* decode IR<4:0> */
case 000: /* [nop] 105200 (OP_N) */
if (UNIT_CPU_TYPE != UNIT_TYPE_1000) /* must be 1000 M/E-series */
return stop_inst; /* trap if not */
return STOP (cpu_ss_unimpl); /* trap if not */
break;
#if defined (HAVE_INT64) /* int64 support available */
@@ -302,7 +316,7 @@ switch (entry) { /* decode IR<4:0> */
case 006: /* .XPAK 105206 (OP_A) */
if (UNIT_CPU_TYPE != UNIT_TYPE_1000) /* must be 1000 */
return stop_inst; /* trap if not */
return STOP (cpu_ss_unimpl); /* trap if not */
if (intrq) { /* interrupt pending? */
PR = err_PC; /* restart instruction */
@@ -310,7 +324,7 @@ switch (entry) { /* decode IR<4:0> */
}
fpop = ReadOp (op[0].word, fp_x); /* read unpacked */
O = fp_nrpack (&fpop, fpop, (int16) AR, fp_x); /* nrm/rnd/pack mantissa, exponent */
O = fp_nrpack (&fpop, fpop, SEXT16 (AR), fp_x); /* nrm/rnd/pack mantissa, exponent */
WriteOp (op[0].word, fpop, fp_x); /* write result */
break;
@@ -372,7 +386,7 @@ switch (entry) { /* decode IR<4:0> */
case 015: /* .XCOM 105215 (OP_A) */
if (UNIT_CPU_TYPE != UNIT_TYPE_1000) /* must be 1000 */
return stop_inst; /* trap if not */
return STOP (cpu_ss_unimpl); /* trap if not */
fpop = ReadOp (op[0].word, fp_x); /* read unpacked */
AR = fp_ucom (&fpop, fp_x); /* complement and rtn exp adj */
@@ -381,7 +395,7 @@ switch (entry) { /* decode IR<4:0> */
case 016: /* ..DCM 105216 (OP_A) */
if (UNIT_CPU_TYPE != UNIT_TYPE_1000) /* must be 1000 */
return stop_inst; /* trap if not */
return STOP (cpu_ss_unimpl); /* trap if not */
if (intrq) { /* interrupt pending? */
PR = err_PC; /* restart instruction */
@@ -395,7 +409,7 @@ switch (entry) { /* decode IR<4:0> */
case 017: /* DDINT 105217 (OP_AAX) */
if (UNIT_CPU_TYPE != UNIT_TYPE_1000) /* must be 1000 */
return stop_inst; /* trap if not */
return STOP (cpu_ss_unimpl); /* trap if not */
if (intrq) { /* interrupt pending? */
PR = err_PC; /* restart instruction */
@@ -418,7 +432,7 @@ switch (entry) { /* decode IR<4:0> */
goto CFER; /* do transfer */
case 021: /* .GOTO 105221 (OP_AK) */
if ((int16) op[1].word < 1) /* index < 1? */
if (SEXT16 (op[1].word) < 1) /* index < 1? */
op[1].word = 1; /* reset min */
sa = PR + op[1].word - 1; /* point to jump target */
@@ -455,7 +469,7 @@ switch (entry) { /* decode IR<4:0> */
op[2].word - 1) * op2[0].word;
}
AR = (op[0].word + op[1].word * BR) & DMASK; /* return element address */
AR = (op[0].word + op[1].word * BR) & R_MASK; /* return element address */
break;
case 023: /* .ENTR 105223 (OP_A) */
@@ -480,8 +494,8 @@ switch (entry) { /* decode IR<4:0> */
WriteW (da++, MA); /* put addr into formal */
}
AR = (uint16) ra; /* return address */
BR = (uint16) da; /* addr of 1st unused formal */
AR = (HP_WORD) ra; /* return address */
BR = (HP_WORD) da; /* addr of 1st unused formal */
break;
case 024: /* .ENTP 105224 (OP_A) */
@@ -490,10 +504,10 @@ switch (entry) { /* decode IR<4:0> */
case 025: /* .PWR2 105225 (OP_RK) */
if (UNIT_CPU_TYPE != UNIT_TYPE_1000) /* must be 1000 */
return stop_inst; /* trap if not */
return STOP (cpu_ss_unimpl); /* trap if not */
fp_unpack (&fpop, &expon, op[0], fp_f); /* unpack value */
expon = expon + (int16) (op[1].word); /* multiply by 2**n */
expon = expon + SEXT16 (op[1].word); /* multiply by 2**n */
fp_pack (&fpop, fpop, expon, fp_f); /* repack value */
AR = fpop.fpk[0]; /* return result */
BR = fpop.fpk[1]; /* to A/B registers */
@@ -501,10 +515,10 @@ switch (entry) { /* decode IR<4:0> */
case 026: /* .FLUN 105226 (OP_R) */
if (UNIT_CPU_TYPE != UNIT_TYPE_1000) /* must be 1000 */
return stop_inst; /* trap if not */
return STOP (cpu_ss_unimpl); /* trap if not */
fp_unpack (&fpop, &expon, op[0], fp_f); /* unpack value */
AR = (int16) expon; /* return expon to A */
AR = expon & R_MASK; /* return expon to A */
BR = fpop.fpk[1]; /* and low mant to B */
break;
@@ -516,12 +530,12 @@ switch (entry) { /* decode IR<4:0> */
do {
WriteW (BR, j); /* write value to address */
j = (j + 1) & DMASK; /* incr value */
j = (j + 1) & D16_MASK; /* incr value */
BR = (BR + 1) & VAMASK; /* incr address */
op[0].word = op[0].word - 1; /* decr count */
if (op[0].word && intrq) { /* more and intr? */
AR = (uint16) sa; /* restore A */
BR = (uint16) sb; /* restore B */
AR = sa; /* restore A */
BR = sb; /* restore B */
PR = err_PC; /* restart instruction */
break;
}
@@ -531,10 +545,10 @@ switch (entry) { /* decode IR<4:0> */
case 030: /* .PACK 105230 (OP_RC) */
if (UNIT_CPU_TYPE != UNIT_TYPE_1000) /* must be 1000 */
return stop_inst; /* trap if not */
return STOP (cpu_ss_unimpl); /* trap if not */
O = fp_nrpack (&fpop, op[0], /* nrm/rnd/pack value */
(int16) (op[1].word), fp_f);
SEXT16 (op[1].word), fp_f);
AR = fpop.fpk[0]; /* return result */
BR = fpop.fpk[1]; /* to A/B registers */
break;
@@ -542,7 +556,7 @@ switch (entry) { /* decode IR<4:0> */
case 031: /* .CFER 105231 (OP_AA) */
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 */
return STOP (cpu_ss_unimpl); /* trap if not */
BR = op[0].word; /* get destination address */
AR = op[1].word; /* get source address */
@@ -562,8 +576,8 @@ switch (entry) { /* decode IR<4:0> */
}
break;
default: /* others undefined */
reason = stop_inst;
default: /* others unimplemented */
reason = STOP (cpu_ss_unimpl);
}
return reason;
@@ -632,11 +646,6 @@ return reason;
execute the extended-precision multiply/divide, and then fixing the
product to a 32-bit double integer. We simulate these directly with 64-
or 32-bit integer arithmetic.
Additional references:
- 93585A Microcode Source (93585-18002 Rev. 2005)
- 93585A Double Integer Instructions Installation and Reference Manual
(93585-90007)
*/
static const OP_PAT op_dbi[16] = {
@@ -692,7 +701,7 @@ switch (entry) { /* decode IR<3:0> */
if (O)
t = ~SIGN32; /* if overflow, rtn max pos */
else
t = (uint32) (t64 & DMASK32); /* else lower 32 bits of result */
t = (uint32) (t64 & D32_MASK); /* else lower 32 bits of result */
#else /* int64 support unavailable */
@@ -814,14 +823,14 @@ switch (entry) { /* decode IR<3:0> */
op[1].dword = t;
goto DSB; /* continue at .DSB */
default: /* others undefined */
default: /* others unimplemented */
t = (AR << 16) | BR; /* set t for NOP */
reason = stop_inst;
reason = STOP (cpu_ss_unimpl);
}
if (reason == SCPE_OK) { /* if return OK */
AR = (t >> 16) & DMASK; /* break result */
BR = t & DMASK; /* into A and B */
AR = UPPER_WORD (t); /* break result */
BR = LOWER_WORD (t); /* into A and B */
}
return reason;

View File

@@ -252,7 +252,8 @@ t_stat cpu_fpp (uint32 IR, uint32 intrq)
OP fpop;
OPS op;
OPSIZE op1_prec, op2_prec, rslt_prec, cvt_prec;
uint16 opcode, rtn_addr, stk_ptr;
HP_WORD rtn_addr, stk_ptr;
uint16 opcode;
uint32 entry;
t_stat reason = SCPE_OK;
@@ -428,8 +429,8 @@ switch (entry) { /* decode IR<6:0> */
case 0134: /* .DDIR 105134 (OP_N) */
return cpu_dbi (0105326, intrq); /* remap to double int handler */
default: /* others undefined */
reason = stop_inst;
default: /* others unimplemented */
reason = STOP (cpu_ss_unimpl);
}
return reason;
@@ -1117,8 +1118,8 @@ switch (entry) { /* decode IR<3:0> */
return reason;
default: /* others undefined */
return stop_inst;
default: /* others unimplemented */
return STOP (cpu_ss_unimpl);
}
AR = op[0].fpk[0]; /* save result */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,7 +1,7 @@
/* hp2100_cpu7.c: HP 1000 VIS and SIGNAL/1000 microcode
Copyright (c) 2008, Holger Veit
Copyright (c) 2006-2016, J. David Bryan
Copyright (c) 2006-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 +26,8 @@
CPU7 Vector Instruction Set and SIGNAL firmware
31-Jan-17 JDB Revised to use tprintf and TRACE_OPND for debugging
26-Jan-17 JDB Removed debug parameters from cpu_ema_* routines
05-Aug-16 JDB Renamed the P register from "PC" to "PR"
24-Dec-14 JDB Added casts for explicit downward conversions
18-Mar-13 JDB Moved EMA helper declarations to hp2100_cpu1.h
@@ -62,85 +64,6 @@
static const OP zero = { { 0, 0, 0, 0, 0 } }; /* DEC 0.0D0 */
/* Vector Instruction Set
The VIS provides instructions that operate on one-dimensional arrays of
floating-point values. Both single- and double-precision operations are
supported. VIS uses the F-Series floating-point processor to handle the
floating-point math.
Option implementation by CPU was as follows:
2114 2115 2116 2100 1000-M 1000-E 1000-F
------ ------ ------ ------ ------ ------ ------
N/A N/A N/A N/A N/A N/A 12824A
The routines are mapped to instruction codes as follows:
Single-Precision Double-Precision
Instr. Opcode Subcod Instr. Opcode Subcod Description
------ ------ ------ ------ ------ ------ -----------------------------
VADD 101460 000000 DVADD 105460 004002 Vector add
VSUB 101460 000020 DVSUB 105460 004022 Vector subtract
VMPY 101460 000040 DVMPY 105460 004042 Vector multiply
VDIV 101460 000060 DVDIV 105460 004062 Vector divide
VSAD 101460 000400 DVSAD 105460 004402 Scalar-vector add
VSSB 101460 000420 DVSSB 105460 004422 Scalar-vector subtract
VSMY 101460 000440 DVSMY 105460 004442 Scalar-vector multiply
VSDV 101460 000460 DVSDV 105460 004462 Scalar-vector divide
VPIV 101461 0xxxxx DVPIV 105461 0xxxxx Vector pivot
VABS 101462 0xxxxx DVABS 105462 0xxxxx Vector absolute value
VSUM 101463 0xxxxx DVSUM 105463 0xxxxx Vector sum
VNRM 101464 0xxxxx DVNRM 105464 0xxxxx Vector norm
VDOT 101465 0xxxxx DVDOT 105465 0xxxxx Vector dot product
VMAX 101466 0xxxxx DVMAX 105466 0xxxxx Vector maximum value
VMAB 101467 0xxxxx DVMAB 105467 0xxxxx Vector maximum absolute value
VMIN 101470 0xxxxx DVMIN 105470 0xxxxx Vector minimum value
VMIB 101471 0xxxxx DVMIB 105471 0xxxxx Vector minimum absolute value
VMOV 101472 0xxxxx DVMOV 105472 0xxxxx Vector move
VSWP 101473 0xxxxx DVSWP 105473 0xxxxx Vector swap
.ERES 101474 -- -- -- -- Resolve array element address
.ESEG 101475 -- -- -- -- Load MSEG maps
.VSET 101476 -- -- -- -- Vector setup
[test] -- -- -- 105477 -- [self test]
Instructions use IR bit 11 to select single- or double-precision format. The
double-precision instruction names begin with "D" (e.g., DVADD vs. VADD).
Most VIS instructions are two words in length, with a sub-opcode immediately
following the primary opcode.
Notes:
1. The .VECT (101460) and .DVCT (105460) opcodes preface a single- or
double-precision arithmetic operation that is determined by the
sub-opcode value. The remainder of the dual-precision sub-opcode values
are "don't care," except for requiring a zero in bit 15.
2. The VIS uses the hardware FPP of the F-Series. FPP malfunctions are
detected by the VIS firmware and are indicated by a memory-protect
violation and setting the overflow flag. Under simulation,
malfunctions cannot occur.
Additional references:
- 12824A Vector Instruction Set User's Manual (12824-90001, Jun-1979).
- VIS Microcode Source (12824-18059, revision 3).
*/
static const OP_PAT op_vis[16] = {
OP_N, OP_AAKAKAKK,OP_AKAKK, OP_AAKK, /* .VECT VPIV VABS VSUM */
OP_AAKK, OP_AAKAKK, OP_AAKK, OP_AAKK, /* VNRM VDOT VMAX VMAB */
OP_AAKK, OP_AAKK, OP_AKAKK, OP_AKAKK, /* VMIN VMIB VMOV VSWP */
OP_AA, OP_A, OP_AAACCC,OP_N /* .ERES .ESEG .VSET [test] */
};
static const t_bool op_ftnret[16] = {
FALSE, TRUE, TRUE, TRUE,
TRUE, TRUE, TRUE, TRUE,
TRUE, TRUE, TRUE, TRUE,
FALSE, TRUE, TRUE, FALSE,
};
/* handle the scalar/vector base ops */
static void vis_svop(uint32 subcode, OPS op, OPSIZE opsize)
{
@@ -361,115 +284,200 @@ for (i=0; i<n; i++) {
}
}
/* Vector Instruction Set
The VIS provides instructions that operate on one-dimensional arrays of
floating-point values. Both single- and double-precision operations are
supported. VIS uses the F-Series floating-point processor to handle the
floating-point math.
Option implementation by CPU was as follows:
2114 2115 2116 2100 1000-M 1000-E 1000-F
------ ------ ------ ------ ------ ------ ------
N/A N/A N/A N/A N/A N/A 12824A
The routines are mapped to instruction codes as follows:
Single-Precision Double-Precision
Instr. Opcode Subcod Instr. Opcode Subcod Description
------ ------ ------ ------ ------ ------ -----------------------------
VADD 101460 000000 DVADD 105460 004002 Vector add
VSUB 101460 000020 DVSUB 105460 004022 Vector subtract
VMPY 101460 000040 DVMPY 105460 004042 Vector multiply
VDIV 101460 000060 DVDIV 105460 004062 Vector divide
VSAD 101460 000400 DVSAD 105460 004402 Scalar-vector add
VSSB 101460 000420 DVSSB 105460 004422 Scalar-vector subtract
VSMY 101460 000440 DVSMY 105460 004442 Scalar-vector multiply
VSDV 101460 000460 DVSDV 105460 004462 Scalar-vector divide
VPIV 101461 0xxxxx DVPIV 105461 0xxxxx Vector pivot
VABS 101462 0xxxxx DVABS 105462 0xxxxx Vector absolute value
VSUM 101463 0xxxxx DVSUM 105463 0xxxxx Vector sum
VNRM 101464 0xxxxx DVNRM 105464 0xxxxx Vector norm
VDOT 101465 0xxxxx DVDOT 105465 0xxxxx Vector dot product
VMAX 101466 0xxxxx DVMAX 105466 0xxxxx Vector maximum value
VMAB 101467 0xxxxx DVMAB 105467 0xxxxx Vector maximum absolute value
VMIN 101470 0xxxxx DVMIN 105470 0xxxxx Vector minimum value
VMIB 101471 0xxxxx DVMIB 105471 0xxxxx Vector minimum absolute value
VMOV 101472 0xxxxx DVMOV 105472 0xxxxx Vector move
VSWP 101473 0xxxxx DVSWP 105473 0xxxxx Vector swap
.ERES 101474 -- -- -- -- Resolve array element address
.ESEG 101475 -- -- -- -- Load MSEG maps
.VSET 101476 -- -- -- -- Vector setup
[test] -- -- -- 105477 -- [self test]
Instructions use IR bit 11 to select single- or double-precision format. The
double-precision instruction names begin with "D" (e.g., DVADD vs. VADD).
Most VIS instructions are two words in length, with a sub-opcode immediately
following the primary opcode.
Notes:
1. The .VECT (101460) and .DVCT (105460) opcodes preface a single- or
double-precision arithmetic operation that is determined by the
sub-opcode value. The remainder of the dual-precision sub-opcode values
are "don't care," except for requiring a zero in bit 15.
2. The VIS uses the hardware FPP of the F-Series. FPP malfunctions are
detected by the VIS firmware and are indicated by a memory-protect
violation and setting the overflow flag. Under simulation,
malfunctions cannot occur.
Additional references:
- 12824A Vector Instruction Set User's Manual (12824-90001, Jun-1979).
- VIS Microcode Source (12824-18059, revision 3).
*/
static const OP_PAT op_vis [16] = {
OP_N, OP_AAKAKAKK, OP_AKAKK, OP_AAKK, /* .VECT VPIV VABS VSUM */
OP_AAKK, OP_AAKAKK, OP_AAKK, OP_AAKK, /* VNRM VDOT VMAX VMAB */
OP_AAKK, OP_AAKK, OP_AKAKK, OP_AKAKK, /* VMIN VMIB VMOV VSWP */
OP_AA, OP_A, OP_AAACCC, OP_N /* .ERES .ESEG .VSET [test] */
};
static const t_bool op_ftnret [16] = {
FALSE, TRUE, TRUE, TRUE,
TRUE, TRUE, TRUE, TRUE,
TRUE, TRUE, TRUE, TRUE,
FALSE, TRUE, TRUE, FALSE,
};
t_stat cpu_vis (uint32 IR, uint32 intrq)
{
static const char *const difficulty [2] = { "hard", "easy" };
t_stat reason = SCPE_OK;
OPS op;
OP ret;
uint32 entry, rtn, rtn1 = 0, subcode = 0;
OP_PAT pattern;
OPSIZE opsize;
t_bool debug = DEBUG_PRI (cpu_dev, DEB_VIS);
uint32 entry, subcode;
HP_WORD rtn = 0;
opsize = (IR & 004000) ? fp_t : fp_f; /* double or single precision */
entry = IR & 017; /* mask to entry point */
pattern = op_vis[entry];
pattern = op_vis [entry];
if (entry == 0) { /* retrieve sub opcode */
subcode = ReadF (PR); /* get it */
if (entry==0) { /* retrieve sub opcode */
ret = ReadOp (PR, in_s); /* get it */
subcode = ret.word;
if (subcode & 0100000) /* special property of ucode */
subcode = AR; /* for reentry */
PR = (PR + 1) & VAMASK; /* bump to real argument list */
pattern = (subcode & 0400) ? OP_AAKAKK : OP_AKAKAKK; /* scalar or vector operation */
}
if (pattern != OP_N) {
if (op_ftnret[entry]) { /* most VIS instrs ignore RTN addr */
ret = ReadOp(PR, in_s);
rtn = rtn1 = ret.word; /* but save it just in case */
if (op_ftnret [entry]) { /* most VIS instrs ignore RTN addr */
rtn = ReadF (PR); /* get it */
PR = (PR + 1) & VAMASK; /* move to next argument */
}
reason = cpu_ops (pattern, op, intrq); /* get instruction operands */
if (reason != SCPE_OK) /* evaluation failed? */
return reason; /* return reason for failure */
}
if (debug) { /* debugging? */
fprintf (sim_deb, ">>CPU VIS: IR = %06o/%06o (", /* print preamble and IR */
IR, subcode);
fprint_sym (sim_deb, err_PC, (t_value *) &IR, /* print instruction mnemonic */
NULL, SWMASK('M'));
fprintf (sim_deb, "), P = %06o", err_PC); /* print location */
fprint_ops (pattern, op); /* print operands */
fputc ('\n', sim_deb); /* terminate line */
}
switch (entry) { /* decode IR<3:0> */
case 000: /* .VECT (OP_special) */
if (subcode & 0400)
vis_svop(subcode,op,opsize); /* scalar/vector op */
else
vis_vvop(subcode,op,opsize); /* vector/vector op */
break;
case 001: /* VPIV (OP_(A)AAKAKAKK) */
vis_vpiv(op,opsize);
break;
case 002: /* VABS (OP_(A)AKAKK) */
vis_vabs(op,opsize);
break;
case 003: /* VSUM (OP_(A)AAKK) */
vis_vsmnm(op,opsize,FALSE);
break;
case 004: /* VNRM (OP_(A)AAKK) */
vis_vsmnm(op,opsize,TRUE);
break;
case 005: /* VDOT (OP_(A)AAKAKK) */
vis_vdot(op,opsize);
break;
case 006: /* VMAX (OP_(A)AAKK) */
vis_minmax(op,opsize,TRUE,FALSE);
break;
case 007: /* VMAB (OP_(A)AAKK) */
vis_minmax(op,opsize,TRUE,TRUE);
break;
case 010: /* VMIN (OP_(A)AAKK) */
vis_minmax(op,opsize,FALSE,FALSE);
break;
case 011: /* VMIB (OP_(A)AAKK) */
vis_minmax(op,opsize,FALSE,TRUE);
break;
case 012: /* VMOV (OP_(A)AKAKK) */
vis_movswp(op,opsize,FALSE);
break;
case 013: /* VSWP (OP_(A)AKAKK) */
vis_movswp(op,opsize,TRUE);
break;
case 014: /* .ERES (OP_(A)AA) */
reason = cpu_ema_eres(&rtn,op[2].word,PR,debug); /* handle the ERES instruction */
PR = rtn;
if (debug)
fprintf (sim_deb,
">>CPU VIS: return .ERES: AR = %06o, BR = %06o, rtn=%s\n",
AR, BR, PR==op[0].word ? "error" : "good");
reason = cpu_ema_eres(&PR,op[2].word,PR); /* handle the ERES instruction */
tprintf (cpu_dev, TRACE_OPND, OPND_FORMAT " return location is P+%u (%s)\n",
PR, IR, PR - err_PC, fmt_ab (PR - rtn));
break;
case 015: /* .ESEG (OP_(A)A) */
reason = cpu_ema_eseg(&rtn,IR,op[0].word,debug); /* handle the ESEG instruction */
PR = rtn;
if (debug)
fprintf (sim_deb,
">>CPU VIS: return .ESEG: AR = %06o , BR = %06o, rtn=%s\n",
AR, BR, rtn==rtn1 ? "error" : "good");
reason = cpu_ema_eseg(&PR,IR,op[0].word); /* handle the ESEG instruction */
tprintf (cpu_dev, TRACE_OPND, OPND_FORMAT " return location is P+%u (%s)\n",
PR, IR, PR - err_PC, fmt_ab (PR - rtn));
break;
case 016: /* .VSET (OP_(A)AAACCC) */
reason = cpu_ema_vset(&rtn,op,debug);
PR = rtn;
if (debug)
fprintf (sim_deb, ">>CPU VIS: return .VSET: AR = %06o BR = %06o, rtn=%s\n",
AR, BR,
rtn==rtn1 ? "error" : (rtn==(rtn1+1) ? "hard" : "easy") );
reason = cpu_ema_vset(&PR,op);
tprintf (cpu_dev, TRACE_OPND, OPND_FORMAT " return location is P+%u (%s)\n",
PR, IR, PR - err_PC,
(PR == rtn
? fmt_ab (0)
: difficulty [PR - rtn - 1]));
break;
case 017: /* [test] (OP_N) */
@@ -477,66 +485,20 @@ switch (entry) { /* decode IR<3:0> */
SR = 0102077; /* test passed code */
PR = (PR + 1) & VAMASK; /* P+2 return for firmware w/VIS */
break;
default: /* others undefined */
reason = stop_inst;
}
default: /* others unimplemented */
reason = STOP (cpu_ss_unimpl);
}
return reason;
}
/* SIGNAL/1000 Instructions
The SIGNAL/1000 instructions provide fast Fourier transforms and complex
arithmetic. They utilize the F-Series floating-point processor and the
Vector Instruction Set.
Option implementation by CPU was as follows:
2114 2115 2116 2100 1000-M 1000-E 1000-F
------ ------ ------ ------ ------ ------ ------
N/A N/A N/A N/A N/A N/A 92835A
The routines are mapped to instruction codes as follows:
Instr. 1000-F Description
------ ------ ----------------------------------------------
BITRV 105600 Bit reversal
BTRFY 105601 Butterfly algorithm
UNSCR 105602 Unscramble for phasor MPY
PRSCR 105603 Unscramble for phasor MPY
BITR1 105604 Swap two elements in array (alternate format)
BTRF1 105605 Butterfly algorithm (alternate format)
.CADD 105606 Complex number addition
.CSUB 105607 Complex number subtraction
.CMPY 105610 Complex number multiplication
.CDIV 105611 Complex number division
CONJG 105612 Complex conjugate
..CCM 105613 Complex complement
AIMAG 105614 Return imaginary part
CMPLX 105615 Form complex number
[nop] 105616 [no operation]
[test] 105617 [self test]
Notes:
1. SIGNAL/1000 ROM data are available from Bitsavers.
Additional references (documents unavailable):
- HP Signal/1000 User Reference and Installation Manual (92835-90002).
- SIGNAL/1000 Microcode Source (92835-18075, revision 2).
*/
/* SIGNAL/1000 routines */
#define RE(x) (x+0)
#define IM(x) (x+2)
static const OP_PAT op_signal[16] = {
OP_AAKK, OP_AAFFKK, OP_AAFFKK,OP_AAFFKK, /* BITRV BTRFY UNSCR PRSCR */
OP_AAAKK, OP_AAAFFKK,OP_AAA, OP_AAA, /* BITR1 BTRF1 .CADD .CSUB */
OP_AAA, OP_AAA, OP_AAA, OP_A, /* .CMPY .CDIV CONJG ..CCM */
OP_AA, OP_AAFF, OP_N, OP_N /* AIMAG CMPLX --- [test]*/
};
/* complex addition helper */
static void sig_caddsub(uint16 addsub,OPS op)
{
@@ -641,6 +603,56 @@ OP p;
(void)fp_exec(004, i, p, NOP); /* imag := ad+bc */
}
/* SIGNAL/1000 Instructions
The SIGNAL/1000 instructions provide fast Fourier transforms and complex
arithmetic. They utilize the F-Series floating-point processor and the
Vector Instruction Set.
Option implementation by CPU was as follows:
2114 2115 2116 2100 1000-M 1000-E 1000-F
------ ------ ------ ------ ------ ------ ------
N/A N/A N/A N/A N/A N/A 92835A
The routines are mapped to instruction codes as follows:
Instr. 1000-F Description
------ ------ ----------------------------------------------
BITRV 105600 Bit reversal
BTRFY 105601 Butterfly algorithm
UNSCR 105602 Unscramble for phasor MPY
PRSCR 105603 Unscramble for phasor MPY
BITR1 105604 Swap two elements in array (alternate format)
BTRF1 105605 Butterfly algorithm (alternate format)
.CADD 105606 Complex number addition
.CSUB 105607 Complex number subtraction
.CMPY 105610 Complex number multiplication
.CDIV 105611 Complex number division
CONJG 105612 Complex conjugate
..CCM 105613 Complex complement
AIMAG 105614 Return imaginary part
CMPLX 105615 Form complex number
[nop] 105616 [no operation]
[test] 105617 [self test]
Notes:
1. SIGNAL/1000 ROM data are available from Bitsavers.
Additional references (documents unavailable):
- HP Signal/1000 User Reference and Installation Manual (92835-90002).
- SIGNAL/1000 Microcode Source (92835-18075, revision 2).
*/
static const OP_PAT op_signal [16] = {
OP_AAKK, OP_AAFFKK, OP_AAFFKK, OP_AAFFKK, /* BITRV BTRFY UNSCR PRSCR */
OP_AAAKK, OP_AAAFFKK, OP_AAA, OP_AAA, /* BITR1 BTRF1 .CADD .CSUB */
OP_AAA, OP_AAA, OP_AAA, OP_A, /* .CMPY .CDIV CONJG ..CCM */
OP_AA, OP_AAFF, OP_N, OP_N /* AIMAG CMPLX --- [test]*/
};
t_stat cpu_signal (uint32 IR, uint32 intrq)
{
t_stat reason = SCPE_OK;
@@ -649,8 +661,6 @@ OP a,b,c,d,p1,p2,p3,p4,m1,m2,wr,wi;
uint32 entry, v, idx1, idx2;
int32 exc, exd;
t_bool debug = DEBUG_PRI (cpu_dev, DEB_SIG);
entry = IR & 017; /* mask to entry point */
if (op_signal [entry] != OP_N) {
@@ -659,15 +669,6 @@ if (op_signal [entry] != OP_N) {
return reason; /* return reason for failure */
}
if (debug) { /* debugging? */
fprintf (sim_deb, ">>CPU SIG: IR = %06o (", IR); /* print preamble and IR */
fprint_sym (sim_deb, err_PC, (t_value *) &IR, /* print instruction mnemonic */
NULL, SWMASK('M'));
fprintf (sim_deb, "), P = %06o", err_PC); /* print location */
fprint_ops (op_signal[entry], op); /* print operands */
fputc ('\n', sim_deb); /* terminate line */
}
switch (entry) { /* decode IR<3:0> */
case 000: /* BITRV (OP_AAKK) */
/* BITRV
@@ -933,8 +934,8 @@ switch (entry) { /* decode IR<3:0> */
break;
case 016: /* invalid */
default: /* others undefined */
reason = stop_inst;
default: /* others unimplemented */
reason = STOP (cpu_ss_unimpl);
}
return reason;

View File

@@ -3,27 +3,38 @@
Copyright (c) 1993-2016, Robert M. Supnik
Copyright (c) 2017 J. David Bryan
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
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
AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Except as contained in this notice, the name of Robert M Supnik shall not
be used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from Robert M Supnik.
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 the authors.
30-Aug-17 JDB Replaced POLL_WAIT with POLL_PERIOD
07-Aug-17 JDB Added "hp_attach"
20-Jul-17 JDB Removed STOP_OFFLINE, STOP_PWROFF stop codes
11-Jul-17 JDB Moved "ibl_copy" to hp2100_cpu.h
26-Jun-17 JDB Moved I/O instruction subopcode constants to hp2100_cpu.c
14-Jun-17 JDB Renamed STOP_RSRV to STOP_UNIMPL (unimplemented instruction)
15-Mar-17 JDB Added global trace flags
27-Feb-17 JDB ibl_copy no longer returns a status code
15-Feb-17 JDB Deleted unneeded guard macro definition
16-Jan-17 JDB Added tracing and console output macros
13-Jan-17 JDB Added fprint_cpu
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
@@ -150,9 +161,6 @@
*/
#ifndef HP2100_DEFS_H_
#define HP2100_DEFS_H_ 0
#include "sim_rev.h"
#include "sim_defs.h"
@@ -188,18 +196,143 @@
#endif
/* Simulator stop and notification codes */
/* Device register display mode flags */
#define REG_X REG_VMIO /* permit symbolic display overrides */
#define REG_A (1u << REG_V_UF + 0) /* default format is -A (one ASCII character) */
#define REG_C (1u << REG_V_UF + 1) /* default format is -C (two ASCII characters) */
#define REG_M (1u << REG_V_UF + 2) /* default format is -M (mnemonic) */
/* Global tracing flags.
Global tracing flags are allocated in descending order, as they may be used
by modules that allocate their own private flags in ascending order. No
check is made for overlapping values.
*/
#define TRACE_CMD (1u << 31) /* trace interface or controller commands */
#define TRACE_INCO (1u << 30) /* trace interface or controller command initiations and completions */
#define TRACE_CSRW (1u << 29) /* trace interface control, status, read, and write actions */
#define TRACE_STATE (1u << 28) /* trace state changes */
#define TRACE_SERV (1u << 27) /* trace unit service scheduling calls and entries */
#define TRACE_PSERV (1u << 26) /* trace periodic unit service scheduling calls and entries */
#define TRACE_XFER (1u << 25) /* trace data receptions and transmissions */
#define TRACE_IOBUS (1u << 24) /* trace I/O bus signals and data words received and returned */
#define DEB_CMDS (1u << 23) /* (old) trace command initiations and completions */
#define DEB_CPU (1u << 22) /* (old) trace words received from and sent to the CPU */
#define DEB_BUF (1u << 21) /* (old) trace data read from and written to the FIFO */
#define DEB_XFER (1u << 20) /* (old) trace data receptions and transmissions */
#define DEB_RWS (1u << 19) /* (old) trace tape reads, writes, and status returns */
#define DEB_RWSC (1u << 18) /* (old) trace disc read/write/status/control commands */
#define DEB_SERV (1u << 17) /* (old) trace unit service scheduling calls and entries */
/* Tracing and console output.
"tprintf" is used to write tracing messages. It does an "fprintf" to the
debug output stream if the stream is open and the trace "flag" is currently
enabled in device "dev". Otherwise, it's a NOP. "..." is the format string
and associated values.
"tpprintf" is identical to "tprintf", except that a device pointer is passed
instead of a device structure.
"TRACING" and "TRACINGP" implement the test conditions for device and device
pointer tracing, respectively. They are used explicitly only when several
trace statements employing the same flag are required, and it is desirable to
avoid repeating the stream and flag test for each one.
"cprintf", "cputs", and "cputc" are used to write messages to the console
and, if console logging is enabled, to the log output stream. They do
"(f)printf", "fputs", or "(f)putc", respectively. "..." is the format string
and associated values, "str" is the string to write, and "ch" is the
character to write.
Implementation notes:
1. The "cputs" macro uses "fputs" for both console and log file output
because "puts" appends a newline, whereas "fputs" does not.
*/
#define TRACING(d,f) (sim_deb != NULL && ((d).dctrl & (f)))
#define TRACINGP(d,f) (sim_deb != NULL && ((d)->dctrl & (f)))
#define tprintf(dev, flag, ...) \
if (TRACING (dev, flag)) \
hp_trace (&(dev), (flag), __VA_ARGS__); \
else \
(void) 0
#define tpprintf(dptr, flag, ...) \
if (TRACINGP (dptr, flag)) \
hp_trace ((dptr), (flag), __VA_ARGS__); \
else \
(void) 0
#define cprintf(...) \
do { \
printf (__VA_ARGS__); \
if (sim_log) \
fprintf (sim_log, __VA_ARGS__); \
} \
while (0)
#define cputs(str) \
do { \
fputs (str, stdout); \
if (sim_log) \
fputs (str, sim_log); \
} \
while (0)
#define cputc(ch) \
do { \
putc (ch); \
if (sim_log) \
fputc (ch, sim_log); \
} \
while (0)
/* Simulation stop and notification codes.
The STOP_* status codes stop the simulator. The "sim_stop_messages" array in
"hp2100_sys.c" contains the message strings that correspond one-for-one with
the stop codes.
The NOTE_* status codes do not stop the simulator. Instead, they inform the
instruction execution loop of special situations that occurred while
processing the current machine instruction..
Implementation notes:
1. Codes before STOP_RERUN cause the instruction to be rerun, so P is backed
up twice. For codes after, P points to the next instruction to be
executed (which is the current instruction for an infinite loop stop).
*/
#define STOP_UNIMPL 1 /* unimplemented instruction stop */
#define STOP_UNSC 2 /* stop on I/O to an unassigned select code */
#define STOP_UNDEF 3 /* undefined instruction stop */
#define STOP_INDIR 4 /* stop on an indirect loop */
#define STOP_RERUN 4 /* stops above here cause the instruction to be re-run */
#define STOP_HALT 5 /* programmed halt */
#define STOP_BRKPNT 6 /* breakpoint */
#define STOP_NOCONN 7 /* no connection */
#define STOP_NOTAPE 8 /* no tape */
#define STOP_EOT 9 /* end of tape */
#define NOTE_IOG 10 /* I/O instr executed */
#define NOTE_INDINT 11 /* indirect intr */
#define STOP_RSRV 1 /* must be 1 */
#define STOP_IODV 2 /* must be 2 */
#define STOP_HALT 3 /* HALT */
#define STOP_IBKPT 4 /* breakpoint */
#define STOP_IND 5 /* indirect loop */
#define NOTE_INDINT 6 /* indirect intr */
#define STOP_NOCONN 7 /* no connection */
#define STOP_OFFLINE 8 /* device offline */
#define STOP_PWROFF 9 /* device powered off */
#define NOTE_IOG 10 /* I/O instr executed */
/* Modifier validation identifiers */
@@ -208,6 +341,54 @@
#define MTAB_XUN (MTAB_XTD | MTAB_VUN)
/* I/O event timing.
I/O events are scheduled for future service by specifying the desired delay
in units of event ticks. Typically, one event tick represents the execution
of one CPU instruction, and this is the way event ticks are defined in the
current simulator implementation. However, the various CPUs themselves not
only vary in speed, but the actual instruction times vary greatly, due to the
presence of block move, compare, and scan instructions. Variations of an
order of magnitude are common, and two orders or more are possible for longer
blocks.
The 24296-90001 Diagnostic Configurator provides a one millisecond timer for
use by the diagnostic programs. The timer is a two-instruction software
loop, plus four instructions of entry/exit overhead, based on the processor
type. The values provided are:
Loop Instr
CPU Count /msec
------ ----- -----
2114 246 496
2115 246 496
2116 309 622
2100 252 508
1000-M 203 410
1000-E 1573 * 1577
* The E-Series TIMER instruction is used instead of a software loop. TIMER
re-executes an internal decrement until the supplied value reaches zero.
To pass diagnostics that time peripheral operations, the simulator assumes
the E-Series execution rate for all devices (0.634 microseconds per event
tick), although this results in needlessly long delays for normal operation.
A correct implementation would change the timing base depending on the
currently selected CPU.
To accommodate possible future variable instruction timing, I/O service
activation times must not assume a constant 0.634 microseconds per event
tick. Delays should be defined in terms of the "uS" (microseconds), "mS"
(milliseconds), and "S" (seconds) macros below.
*/
#define USEC_PER_EVENT 0.634 /* average CPU instruction time in microseconds */
#define uS(t) (uint32) ((t) > USEC_PER_EVENT ? (t) / USEC_PER_EVENT + 0.5 : 1)
#define mS(t) (uint32) (((t) * 1000.0) / USEC_PER_EVENT + 0.5)
#define S(t) (uint32) (((t) * 1000000.0) / USEC_PER_EVENT + 0.5)
/* Architectural constants.
These macros specify the width, sign location, value mask, and minimum and
@@ -217,11 +398,52 @@
The HP_WORD type is used to declare variables that represent 16-bit registers
or buses in hardware.
Implementation notes:
1. The HP_WORD type is a 32-bit unsigned type, instead of the more logical
16-bit unsigned type. There are two reasons for this. First, SCP
requires that scalars referenced by REG (register) entries be 32 bits in
size. Second, IA-32 processors execute instructions with 32-bit operands
much faster than those with 16-bit operands.
Using 16-bit operands omits the masking required for 32-bit values. For
example, the code generated for the following operations is as follows:
uint16 a, b, c;
a = b + c & 0xFFFF;
movzwl _b, %eax
addw _c, %ax
movw %ax, _a
uint32 x, y, z;
x = y + z & 0xFFFF;
movl _z, %eax
addl _y, %eax
andl $65535, %eax
movl %eax, _x
However, the first case uses operand override prefixes, which require
substantially more time to decode (6 clock cycles vs. 1 clock cycle).
This time outweighs the additional 32-bit AND instruction, which executes
in 1 clock cycle.
2. The MEMORY_WORD type is a 16-bit unsigned type, corresponding with the
16-bit main memory in the HP 21xx/1000. Unlike the general data type,
which is a 32-bit type for speed, main memory does not benefit from the
faster 32-bit execution on IA-32 processors, as only one instruction in
the mem_read and mem_write routines has an operand override that invokes
the slower instruction fetch path. There is a negligible difference in
the Memory Pattern Test diagnostic execution speeds for the uint32 vs.
uint16 definition, whereas the VM requirements are doubled for the
former.
*/
typedef uint16 HP_WORD; /* HP 16-bit data word representation */
#define R_MASK 0177777u /* 16-bit register mask */
typedef uint32 HP_WORD; /* HP 16-bit data word representation */
typedef uint16 MEMORY_WORD; /* HP 16-bit memory word representation */
#define D4_WIDTH 4 /* 4-bit data bit width */
#define D4_MASK 0017u /* 4-bit data mask */
@@ -267,6 +489,11 @@ typedef uint16 HP_WORD; /* HP 16-bit data word r
#define S32_OVFL_MASK ((t_uint64) D32_UMAX << D32_WIDTH | \
D32_SIGN) /* 32-bit signed overflow mask */
#define LSB 1u /* least-significant bit */
#define D16_SIGN_LSB (D16_SIGN | LSB) /* bit 15 and bit 0 */
#define R_MASK 0177777u /* 16-bit register mask */
/* Memory constants */
@@ -293,6 +520,40 @@ typedef uint16 HP_WORD; /* HP 16-bit data word r
#define DV_SMAX ((1u << (DV_WIDTH - 1)) - 1) /* data value signed maximum (2 ** 15 - 1) */
/* Memory address macros.
These macros convert between logical and physical addresses. The functions
provided are:
- PAGE -- extract the page number part of a physical address
- OFFSET -- extract the offset part of a physical address
- TO_PA -- merge a page number and offset into a physical address
*/
#define PAGE(p) ((p) >> PG_WIDTH & PG_MASK)
#define OFFSET(p) ((p) & OF_MASK)
#define TO_PA(b,o) (((uint32) (b) & PG_MASK) << PG_WIDTH | (uint32) (o) & OF_MASK)
/* Memory access classifications.
The access classification determines the DMS map set and protections to use
when reading or writing memory words. The classification also is used to
label each data access when tracing is enabled. When DMS is disabled, or
when the CPU is one of the 21xx models, the classification is irrelevant.
*/
typedef enum {
Fetch, /* instruction fetch, current map */
Data, /* data access, current map */
Data_Alternate, /* data access, alternate map */
Data_System, /* data access, system map */
Data_User, /* data access, user map */
DMA_Channel_1, /* DMA channel 1, port A map */
DMA_Channel_2 /* DMA channel 2, port B map */
} ACCESS_CLASS;
/* Portable conversions.
SIMH is written with the assumption that the defined-size types (e.g.,
@@ -302,28 +563,28 @@ typedef uint16 HP_WORD; /* HP 16-bit data word r
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.
...will not guarantee that the upper 16 bits of "negative_value_32" are all
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
- SEXT8 -- signed 8-bit value sign-extended to int32
- SEXT16 -- signed 16-bit value sign-extended to int32
- NEG8 -- signed 8-bit value negated
- NEG16 -- signed 16-bit value negated
- NEG32 -- signed 32-bit value 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.
1. The SEXTn and INTn routines assume that their values are masked to
exactly n 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 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)
@@ -371,12 +632,43 @@ typedef enum {
#define TO_DWORD(u,l) ((uint32) (u) << D16_WIDTH | (l))
/* Portable conversions (sign-extension, unsigned-to-signed) */
/* CPU instruction symbolic source.
#define SEXT(x) ((int32) (((x) & SIGN)? ((x) | ~DMASK): ((x) & DMASK)))
The memory-reference group (MRG) instructions do not specify full logical
addresses of their targets. Instead, they specify offsets from either the
base page or the current page. Instructions specifying base-page offsets are
always displayed with target addresses between 0000-1777. The display and
parsing of instructions specifying current-page offsets depends on the source
of the instructions.
If the current-page CPU instruction is contained in main memory, the current
page is taken from the address of the word containing the instruction, and
the full target address between 00000-77777 is displayed or parsed. However,
if the instruction is contained in a device buffer, e.g., a disc drive sector
buffer, the destination memory address is unknown until the instruction is
transferred to memory. In this case, the target address is displayed or
parsed as the offset prefixed with the letter "C" (e.g., "LDA C 1200"). In
order to present the proper symbolic behavior, the mnemonic formatter and
parser must know the source of the request.
Additionally, display requests from the EXAMINE command have preloaded a
value array with the maximum number of words required to encode the longest
instruction. This is inefficient, as only a fraction of the instruction set
requires more than one word. For EXAMINE commands entered by the user at the
SCP prompt, this is unimportant. However, for calls from the CPU instruction
trace routine, the overhead is significant. In the latter case, the array is
loaded only with a single word, and the mnemonic formatter loads additional
words if the specific instruction to be displayed requires them.
*/
typedef enum {
Device_Symbol, /* called for an EXAMINE <device> or DEPOSIT <device> command */
CPU_Symbol, /* called for an EXAMINE CPU or DEPOSIT CPU command */
CPU_Trace /* called for a CPU trace command */
} SYMBOL_SOURCE;
/* Memory */
/* Memory constants (deprecated) */
#define MEMSIZE (cpu_unit.capac) /* actual memory size */
#define VA_N_SIZE 15 /* virtual addr size */
@@ -386,7 +678,7 @@ typedef enum {
#define PASIZE (1 << PA_N_SIZE)
#define PAMASK (PASIZE - 1) /* phys addr mask */
/* Architectural constants */
/* Architectural constants (deprecated) */
#define SIGN32 020000000000 /* 32b sign */
#define DMASK32 037777777777 /* 32b data mask/maximum value */
@@ -403,20 +695,10 @@ typedef enum {
#define POLL_RATE 100 /* poll 100 times per second */
#define POLL_FIRST 1 /* first poll is "immediate" */
#define POLL_WAIT 15800 /* initial poll ~ 10 msec. */
#define POLL_PERIOD mS (10) /* 10 millisecond poll period */
typedef enum { INITIAL, SERVICE } POLLMODE; /* poll synchronization modes */
/* I/O instruction sub-opcodes */
#define soHLT 0 /* halt */
#define soFLG 1 /* set/clear flag */
#define soSFC 2 /* skip on flag clear */
#define soSFS 3 /* skip on flag set */
#define soMIX 4 /* merge into A/B */
#define soLIX 5 /* load into A/B */
#define soOTX 6 /* output from A/B */
#define soCTL 7 /* set/clear control */
/* I/O devices - fixed select code assignments */
@@ -464,33 +746,6 @@ typedef enum { INITIAL, SERVICE } POLLMODE; /* poll synchronization
#define VARDEV 010 /* start of variable assignments */
#define MAXDEV 077 /* end of select code range */
/* IBL assignments */
#define IBL_V_SEL 14 /* ROM select <15:14> */
#define IBL_M_SEL 03
#define IBL_PTR 0000000 /* ROM 0: 12992K paper tape reader (PTR) */
#define IBL_DP 0040000 /* ROM 1: 12992A 7900 disc (DP) */
#define IBL_DQ 0060000 /* ROM 1: 12992A 2883 disc (DQ) */
#define IBL_MS 0100000 /* ROM 2: 12992D 7970 tape (MS) */
#define IBL_DS 0140000 /* ROM 3: 12992B 7905/06/20/25 disc (DS) */
#define IBL_MAN 0010000 /* RPL/manual boot <13:12> */
#define IBL_V_DEV 6 /* select code <11:6> */
#define IBL_OPT 0000070 /* options in <5:3> */
#define IBL_DP_REM 0000001 /* DP removable <0:0> */
#define IBL_DS_HEAD 0000003 /* DS head number <1:0> */
#define IBL_LNT 64 /* boot ROM length in words */
#define IBL_MASK (IBL_LNT - 1) /* boot length mask */
#define IBL_DPC (IBL_LNT - 2) /* DMA ctrl word */
#define IBL_END (IBL_LNT - 1) /* last location */
#define IBL_S_CLR 0000000 /* ibl_copy mask to clear the S register */
#define IBL_S_NOCLR 0177777 /* ibl_copy mask to preserve the S register */
#define IBL_S_NOSET 0000000 /* ibl_copy mask to preserve the S register */
#define IBL_SET_SC(s) ((s) << IBL_V_DEV) /* position the select code in the S register */
typedef uint16 BOOT_ROM [IBL_LNT]; /* boot ROM data */
/* I/O backplane signals.
@@ -599,20 +854,50 @@ typedef enum {
#define D_FF(b) (FLIP_FLOP) ((b) != 0) /* use a Boolean expression for a D flip-flop */
/* I/O structures */
/* I/O structures.
typedef struct dib DIB; /* incomplete definition */
The Device Information Block (DIB) allows devices to be relocated in the
machine's I/O space. Each DIB contains a pointer to the device interface
routine, a value corresponding to the location of the interface card in the
CPU's I/O card cage (which determines the card's select code), and a card
index if the interface routine services multiple cards.
typedef uint32 IOHANDLER (DIB *dibptr, /* I/O signal handler prototype */
IOCYCLE signal_set,
uint32 stat_data);
struct dib { /* Device information block */
IOHANDLER *io_handler; /* pointer to device's I/O signal handler */
uint32 select_code; /* device's select code */
uint32 card_index; /* device's card index for state variables */
Implementation notes:
1. The select_code and card_index fields could be smaller than the defined
32-bit sizes, but IA-32 processors execute instructions with 32-bit
operands much faster than those with 16- or 8-bit operands.
2. The DIB_REGS macro provides hidden register entries needed to save and
restore the state of a DIB. Only the potentially variable fields are
referenced. In particular, the "io_interface" field must not be saved,
as the address of the device's interface routine may change from version
to version of the simulator.
*/
#define SC_MAX 077 /* the maximum select code */
#define SC_MASK 077u /* the mask for the select code */
#define SC_BASE 8 /* the radix for the select code */
typedef struct dib DIB; /* an incomplete definition */
typedef uint32 IOHANDLER /* the I/O device interface function prototype */
(DIB *dibptr, /* a pointer to the device information block */
IOCYCLE signal_set, /* a set of inbound signals */
uint32 stat_data); /* a 32-bit inbound value */
struct dib { /* the Device Information Block */
IOHANDLER *io_handler; /* the device's I/O interface function pointer */
uint32 select_code; /* the device's select code (02-77) */
uint32 card_index; /* the card index if multiple interfaces are supported */
};
#define DIB_REGS(dib) \
/* Macro Name Location Width Flags */ \
/* ------ ------- -------------------------- ----- ----------------- */ \
{ ORDATA (DIBSC, dib.select_code, 32), PV_LEFT | REG_HRO }
/* I/O signal and status macros.
@@ -654,12 +939,12 @@ struct dib { /* Device information bl
if the Boolean test B is true.
*/
#define IONEXT(I) (IOSIGNAL) ((I) & (IOCYCLE) (- (int32) (I))) /* extract next I/O signal to handle */
#define IONEXT(I) (IOSIGNAL) ((I) & ~(I) + 1) /* extract next I/O signal to handle */
#define IOADDSIR(I) ((I) & IOIRQSET ? (I) | ioSIR : (I)) /* add SIR if IRQ state might change */
#define IORETURN(E,D) ((uint32) ((E) << 16 | (D) & DMASK)) /* form I/O handler return value */
#define IOSTATUS(C) ((t_stat) ((C) >> 16) & DMASK) /* extract I/O status from combined value */
#define IODATA(C) ((uint16) ((C) & DMASK)) /* extract data from combined value */
#define IORETURN(E,D) ((uint32) ((E) << D16_WIDTH | (D) & D16_MASK)) /* form I/O handler return value */
#define IOSTATUS(C) ((t_stat) ((C) >> D16_WIDTH) & D16_MASK) /* extract I/O status from combined value */
#define IODATA(C) ((uint16) ((C) & D16_MASK)) /* extract data from combined value */
#define IOPOWERON(P) (P)->io_handler ((P), ioPON | ioPOPIO | ioCRS, 0) /* send power-on signals to handler */
#define IOPRESET(P) (P)->io_handler ((P), ioPOPIO | ioCRS, 0) /* send PRESET signals to handler */
@@ -736,26 +1021,81 @@ struct dib { /* Device information bl
#define setstdSRQ(N) setSRQ (dibptr->select_code, N.flag);
/* CPU state */
/* Bitset formatting.
See the comments at the "fmt_bitset" function (hp3000_sys.c) for details of
the specification of bitset names and format structures.
*/
typedef enum { /* direction of interpretation */
msb_first, /* left-to-right */
lsb_first /* right-to-left */
} BITSET_DIRECTION;
typedef enum { /* alternate names */
no_alt, /* no alternates are present in the name array */
has_alt /* the name array contains alternates */
} BITSET_ALTERNATE;
typedef enum { /* trailing separator */
no_bar, /* omit a trailing separator */
append_bar /* append a trailing separator */
} BITSET_BAR;
typedef const char *const BITSET_NAME; /* a bit name string pointer */
typedef struct { /* bit set format descriptor */
uint32 name_count; /* count of bit names */
BITSET_NAME *names; /* pointer to an array of bit names */
uint32 offset; /* offset from LSB to first bit */
BITSET_DIRECTION direction; /* direction of interpretation */
BITSET_ALTERNATE alternate; /* alternate interpretations presence */
BITSET_BAR bar; /* trailing separator choice */
} BITSET_FORMAT;
/* Bitset format specifier initialization */
#define FMT_INIT(names,offset,dir,alt,bar) \
sizeof (names) / sizeof (names) [0], \
(names), (offset), (dir), (alt), (bar)
/* System interface global data structures */
extern const HP_WORD odd_parity [256]; /* a table of parity bits for odd parity */
/* System interface global SCP support routines declared in scp.h
extern t_stat sim_load (FILE *fptr, CONST char *cptr, CONST char *fnam, int flag);
extern t_stat fprint_sym (FILE *ofile, t_addr addr, t_value *val, UNIT *uptr, int32 sw);
extern t_stat parse_sym (CONST char *cptr, t_addr addr, UNIT *uptr, t_value *val, int32 sw);
*/
/* System interface global SCP support routines */
extern t_stat hp_attach (UNIT *uptr, CONST char *cptr);
extern t_stat hp_set_dib (UNIT *uptr, int32 count, CONST char *cptr, void *desc);
extern t_stat hp_show_dib (FILE *st, UNIT *uptr, int32 count, CONST void *desc);
/* System interface global utility routines */
extern t_stat fprint_cpu (FILE *ofile, t_addr addr, t_value *val, uint32 radix, SYMBOL_SOURCE source);
extern const char *fmt_char (uint32 charval);
extern const char *fmt_bitset (uint32 bitset, const BITSET_FORMAT bitfmt);
extern void hp_trace (DEVICE *dptr, uint32 flag, ...);
extern t_bool hp_device_conflict (void);
extern void hp_enbdis_pair (DEVICE *ccptr, DEVICE *dcptr);
/* I/O state */
extern uint32 dev_prl [2], dev_irq [2], dev_srq [2]; /* I/O signal vectors */
/* CPU functions */
extern t_stat ibl_copy (const BOOT_ROM rom, int32 dev, uint32 sr_clear, uint32 sr_set);
extern void hp_enbdis_pair (DEVICE *ccp, DEVICE *dcp);
/* System functions */
extern const char *fmt_char (uint8 ch);
extern t_stat hp_setsc (UNIT *uptr, int32 val, CONST char *cptr, void *desc);
extern t_stat hp_setdev (UNIT *uptr, int32 val, CONST char *cptr, void *desc);
extern t_stat hp_showsc (FILE *st, UNIT *uptr, int32 val, CONST void *desc);
extern t_stat hp_showdev (FILE *st, UNIT *uptr, int32 val, CONST void *desc);
extern t_bool hp_fprint_stopped (FILE *st, t_stat reason);
/* Device-specific functions */
extern int32 sync_poll (POLLMODE poll_mode);
#endif

View File

@@ -25,6 +25,8 @@
DI 12821A Disc Interface
15-Mar-17 JDB Converted debug fprintfs to tpprintfs
10-Mar-17 JDB Added IOBUS to the debug table
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
@@ -177,6 +179,33 @@
#define TAG_MASK (TAG_ATN | TAG_EOI | TAG_EDT | TAG_LBR)
static const BITSET_NAME tag_names [] = { /* Bus signal names */
"ATN", /* bit 16 */
"EOI", /* bit 17 */
"EDT", /* bit 18 */
"LBR" /* bit 19 */
};
static const BITSET_FORMAT tag_format = /* names, offset, direction, alternates, bar */
{ FMT_INIT (tag_names, 16, lsb_first, no_alt, no_bar) };
/* Bus signals */
static const BITSET_NAME bus_names [] = { /* Bus signal names */
"ATN", /* bit 0 = attention */
"EOI", /* bit 1 = end or identify */
"DAV", /* bit 2 = data available */
"NRFD", /* bit 3 = not ready for data */
"NDAC", /* bit 4 = not data accepted */
"REN", /* bit 5 = remote enable */
"IFC", /* bit 6 = interface clear */
"SRQ" /* bit 7 = service request */
};
static const BITSET_FORMAT bus_format = /* names, offset, direction, alternates, bar */
{ FMT_INIT (bus_names, 0, lsb_first, no_alt, no_bar) };
/* FIFO access modes */
@@ -207,7 +236,6 @@ static void master_reset (CARD_ID card);
static void update_state (CARD_ID card);
static void fifo_load (CARD_ID card, uint16 data, FIFO_ACCESS access);
static uint16 fifo_unload (CARD_ID card, FIFO_ACCESS access);
static void fprint_bus (FILE *file, char *format, uint8 cntl);
@@ -251,7 +279,8 @@ DEVICE dc_dev = {
0, /* debug control flags */
di_deb, /* debug flag name table */
NULL, /* memory size change routine */
NULL }; /* logical device name */
NULL /* logical device name */
};
@@ -280,13 +309,14 @@ static RESPONDER *bus_respond [card_count] = { &da_bus_respond, NULL, NULL };
DEBTAB di_deb [] = {
{ "CPU", DEB_CPU },
{ "CMDS", DEB_CMDS },
{ "BUF", DEB_BUF },
{ "XFER", DEB_XFER },
{ "RWSC", DEB_RWSC },
{ "SERV", DEB_SERV },
{ NULL, 0 }
{ "RWSC", DEB_RWSC },
{ "CMDS", DEB_CMDS },
{ "CPU", DEB_CPU },
{ "BUF", DEB_BUF },
{ "XFER", DEB_XFER },
{ "SERV", DEB_SERV },
{ "IOBUS", TRACE_IOBUS },
{ NULL, 0 }
};
@@ -408,7 +438,6 @@ DEBTAB di_deb [] = {
optimization.
*/
uint32 di_io (DIB *dibptr, IOCYCLE signal_set, uint32 stat_data)
{
static const char * const output_state [] = { "Control", "Data" };
@@ -434,9 +463,7 @@ while (working_set) {
di_card->flag = CLEAR; /* clear the flag */
di_card->flagbuf = CLEAR; /* and flag buffer */
if (DEBUG_PRJ (dptrs [card], DEB_CMDS))
fprintf (sim_deb, ">>%s cmds: [CLF] Flag cleared\n",
dptrs [card]->name);
tpprintf (dptrs [card], DEB_CMDS, "[CLF] Flag cleared\n");
if (update_required) /* if the card state has changed */
update_state (card); /* then update the state */
@@ -444,9 +471,7 @@ while (working_set) {
case ioSTF: /* set flag flip-flop */
if (DEBUG_PRJ (dptrs [card], DEB_CMDS))
fprintf (sim_deb, ">>%s cmds: [STF] Flag set\n",
dptrs [card]->name);
tpprintf (dptrs [card], DEB_CMDS, "[STF] Flag set\n");
/* fall into ENF handler */
@@ -472,9 +497,8 @@ while (working_set) {
di_card->status_register &= ~STAT_IRL; /* clear the input register loaded status */
if (FIFO_EMPTY && di_card->eor == CLEAR) { /* is the FIFO empty and end of record not seen? */
if (di_card->srq == SET && DEBUG_PRJ (dptrs [card], DEB_CMDS))
fprintf (sim_deb, ">>%s cmds: SRQ cleared\n",
dptrs [card]->name);
if (di_card->srq == SET)
tpprintf (dptrs [card], DEB_CMDS, "SRQ cleared\n");
di_card->srq = CLEAR; /* clear SRQ */
update_required = FALSE; /* the card state does not change */
@@ -505,10 +529,8 @@ while (working_set) {
data = di_card->status_register; /* return the status word */
}
if (DEBUG_PRJ (dptrs [card], DEB_CPU))
fprintf (sim_deb, ">>%s cpu: [LIx%s] %s = %06o\n",
dptrs [card]->name, hold_or_clear,
input_state [di_card->control], data);
tpprintf (dptrs [card], DEB_CPU, "[LIx%s] %s = %06o\n",
hold_or_clear, input_state [di_card->control], data);
if (update_required && !(signal_set & ioCLF)) /* if an update is required and CLF is not present, */
update_state (card); /* update the state, else ioCLF will update it */
@@ -520,10 +542,8 @@ while (working_set) {
case ioIOO: /* I/O data output */
data = IODATA (stat_data); /* get the data value */
if (DEBUG_PRJ (dptrs [card], DEB_CPU))
fprintf (sim_deb, ">>%s cpu: [OTx%s] %s = %06o\n",
dptrs [card]->name, hold_or_clear,
output_state [di_card->control], data);
tpprintf (dptrs [card], DEB_CPU, "[OTx%s] %s = %06o\n",
hold_or_clear, output_state [di_card->control], data);
if (di_card->control == SET) { /* is the card in data mode? */
if (signal_set & ioEDT) /* if end of DCPC transfer */
@@ -547,9 +567,8 @@ while (working_set) {
fifo_load (card, data, cpu_access); /* load the data word into the FIFO */
if (FIFO_FULL && (di_card->bus_cntl & BUS_NRFD)) { /* FIFO full and listener not ready? */
if (di_card->srq == SET && DEBUG_PRJ (dptrs [card], DEB_CMDS))
fprintf (sim_deb, ">>%s cmds: SRQ cleared\n",
dptrs [card]->name);
if (di_card->srq == SET)
tpprintf (dptrs [card], DEB_CMDS, "SRQ cleared\n");
di_card->srq = CLEAR; /* clear SRQ */
update_required = FALSE; /* the card state does not change */
@@ -638,16 +657,12 @@ while (working_set) {
di_card->flag = SET; /* set the flag */
di_card->flagbuf = SET; /* and flag buffer */
if (DEBUG_PRJ (dptrs [card], DEB_CMDS))
fprintf (sim_deb, ">>%s cmds: [POPIO] Flag set\n",
dptrs [card]->name);
tpprintf (dptrs [card], DEB_CMDS, "[POPIO] Flag set\n");
break;
case ioCRS: /* control reset */
if (DEBUG_PRJ (dptrs [card], DEB_CMDS))
fprintf (sim_deb, ">>%s cmds: [CRS] Master reset\n",
dptrs [card]->name);
tpprintf (dptrs [card], DEB_CMDS, "[CRS] Master reset\n");
di_card->status_register &= /* clear listen and talk status */
~(STAT_LSTN | STAT_TALK);
@@ -671,15 +686,8 @@ while (working_set) {
case ioCLC: /* clear control flip-flop */
di_card->control = CLEAR; /* clear control */
if (DEBUG_PRJ (dptrs [card], DEB_CMDS)) {
fprintf (sim_deb, ">>%s cmds: [CLC%s] Control cleared (configure mode)",
dptrs [card]->name, hold_or_clear);
if (signal_set & ioCLF) /* if ioCLF is given, */
fputs (", master reset\n", sim_deb); /* then report a master reset */
else
fputc ('\n', sim_deb);
}
tpprintf (dptrs [card], DEB_CMDS, "[CLC%s] Control cleared (configure mode)%s\n",
hold_or_clear, (signal_set & ioCLF ? ", master reset" : ""));
if (signal_set & ioCLF) /* if ioCLF is given, */
master_reset (card); /* then do a master reset */
@@ -689,16 +697,13 @@ while (working_set) {
case ioSTC: /* set control flip-flop */
di_card->control = SET; /* set control */
if (DEBUG_PRJ (dptrs [card], DEB_CMDS))
fprintf (sim_deb, ">>%s cmds: [STC%s] Control set (data mode)\n",
dptrs [card]->name, hold_or_clear);
tpprintf (dptrs [card], DEB_CMDS, "[STC%s] Control set (data mode)\n",
hold_or_clear);
break;
case ioEDT: /* end data transfer */
if (DEBUG_PRJ (dptrs [card], DEB_CPU))
fprintf (sim_deb, ">>%s cpu: [EDT] DCPC transfer ended\n",
dptrs [card]->name);
tpprintf (dptrs [card], DEB_CPU, "[EDT] DCPC transfer ended\n");
break;
@@ -1017,10 +1022,8 @@ CARD_ID other;
uint32 acceptors, unit;
t_bool accepted = FALSE;
if (DEBUG_PRJ (dptrs [card], DEB_XFER)) {
fprintf (sim_deb, ">>%s xfer: HP-IB DIO %03o available ", dptrs [card]->name, data);
fprint_bus (sim_deb, "[%s]\n", di [card].bus_cntl);
}
tpprintf (dptrs [card], DEB_XFER, "HP-IB DIO %03o signals %s available\n",
data, fmt_bitset (di [card].bus_cntl, bus_format));
if (dptrs [card]->flags & DEV_DIAG) /* is this a diagnostic run? */
for (other = first_card; other <= last_card; other++) { /* look through the list of cards */
@@ -1048,9 +1051,8 @@ else if ((di [card].bus_cntl & BUS_PPOLL) != BUS_PPOLL) { /* this is a normal
}
}
if (DEBUG_PRJ (dptrs [card], DEB_XFER) && !accepted)
fprintf (sim_deb, ">>%s xfer: HP-IB no acceptors\n",
dptrs [card]->name);
if (!accepted)
tpprintf (dptrs [card], DEB_XFER, "HP-IB no acceptors\n");
return accepted;
}
@@ -1114,21 +1116,18 @@ new_denials = di [card].bus_cntl & deny; /* get the changing deni
di [card].bus_cntl = new_state; /* establish the new control state */
if (DEBUG_PRJ (dptrs [card], DEB_XFER)) {
if (unit == CONTROLLER)
fprintf (sim_deb, ">>%s xfer: HP-IB card %d", dptrs [card]->name, card);
else
fprintf (sim_deb, ">>%s xfer: HP-IB address %d",
dptrs [card]->name, GET_BUSADR (dptrs [card]->units [unit].flags));
if (new_assertions)
fprint_bus (sim_deb, " asserted [%s]", new_assertions);
if (new_denials)
fprint_bus (sim_deb, " denied [%s]", new_denials);
fprint_bus (sim_deb, ", bus is [%s]\n", new_state);
}
if (unit == CONTROLLER)
tpprintf (dptrs [card], DEB_XFER, "HP-IB card %d asserted %s denied %s bus is %s\n",
card,
fmt_bitset (new_assertions, bus_format),
fmt_bitset (new_denials, bus_format),
fmt_bitset (new_state, bus_format));
else
tpprintf (dptrs [card], DEB_XFER, "HP-IB address %d asserted %s denied %s bus is %s\n",
GET_BUSADR (dptrs [card]->units [unit].flags),
fmt_bitset (new_assertions, bus_format),
fmt_bitset (new_denials, bus_format),
fmt_bitset (new_state, bus_format));
if ((dptrs [card]->flags & DEV_DIAG) /* is the card in diagnostic mode? */
|| (new_assertions & ASSERT_SET) /* or are changed signals in the */
@@ -1158,9 +1157,8 @@ if ((dptrs [card]->flags & DEV_DIAG) /* is the card i
}
}
if (DEBUG_PRJ (dptrs [card], DEB_XFER) & !responded)
fprintf (sim_deb, ">>%s xfer: HP-IB no responders\n",
dptrs [card]->name);
if (!responded)
tpprintf (dptrs [card], DEB_XFER, "HP-IB no responders\n");
}
if ((new_state & BUS_PPOLL) == BUS_PPOLL) /* was a parallel poll requested? */
@@ -1191,10 +1189,9 @@ if (response == SET) { /* enable the poll respo
else /* disable the poll response */
di [card].poll_response &= ~PPR (address); /* by clearing the response bit */
if (DEBUG_PRJ (dptrs [card], DEB_XFER)
&& previous_response != di [card].poll_response)
fprintf (sim_deb, ">>%s xfer: HP-IB address %d parallel poll response %s\n",
dptrs [card]->name, address, (response == SET ? "enabled" : "disabled"));
if (previous_response != di [card].poll_response)
tpprintf (dptrs [card], DEB_XFER, "HP-IB address %d parallel poll response %s\n",
address, (response == SET ? "enabled" : "disabled"));
return;
}
@@ -1249,9 +1246,8 @@ if (dptrs [card]->flags & DEV_DIAG) /* is this a diagnos
PPR (GET_DIADR (dptrs [other]->flags));
if (response) { /* is a poll response indicated? */
if (DEBUG_PRJ (dptrs [card], DEB_XFER))
fprintf (sim_deb, ">>%s xfer: HP-IB parallel poll DIO %03o\n",
dptrs [card]->name, response);
tpprintf (dptrs [card], DEB_XFER, "HP-IB parallel poll DIO %03o\n",
response);
while (di [card].fifo_count != FIFO_SIZE) /* fill the card FIFO with the responses */
fifo_load (card, (uint16) response, diag_access); /* (hardware feature) */
@@ -1274,9 +1270,8 @@ return;
static t_bool di_bus_accept (CARD_ID card, uint8 data)
{
if (DEBUG_PRJ (dptrs [card], DEB_XFER))
fprintf (sim_deb, ">>%s xfer: HP-IB card %d accepted data %03o \n",
dptrs [card]->name, card, data);
tpprintf (dptrs [card], DEB_XFER, "HP-IB card %d accepted data %03o\n",
card, data);
fifo_load (card, data, bus_access); /* load the data byte into the FIFO */
update_state (card); /* and update the card state */
@@ -1339,9 +1334,7 @@ di [card].status_register &= /* clear the status flip
di [card].input_data_register = 0; /* clear the input data register */
di [card].fifo_count = 0; /* clear the FIFO */
if (DEBUG_PRJ (dptrs [card], DEB_BUF))
fprintf (sim_deb, ">>%s buf: FIFO cleared\n",
dptrs [card]->name);
tpprintf (dptrs [card], DEB_BUF, "FIFO cleared\n");
return;
}
@@ -1465,10 +1458,9 @@ else
di_card->srq = CLEAR; /* otherwise, DCPC service is not needed */
if (DEBUG_PRJ (dptrs [card], DEB_CMDS)
&& di_card->srq != previous_state)
fprintf (sim_deb, ">>%s cmds: SRQ %s\n",
dptrs [card]->name, di_card->srq == SET ? "set" : "cleared");
if (di_card->srq != previous_state)
tpprintf (dptrs [card], DEB_CMDS, "SRQ %s\n",
di_card->srq == SET ? "set" : "cleared");
if (di_card->status_register & STAT_IRL /* is the input register loaded */
@@ -1487,9 +1479,7 @@ if (di_card->status_register & STAT_IRL /* is the input register
&& di_card->status_register & STAT_IFC /* and IFC is asserted on the bus */
&& di_card->cntl_register & CNTL_IFC) { /* and notification is wanted? */
if (DEBUG_PRJ (dptrs [card], DEB_CMDS))
fprintf (sim_deb, ">>%s cmds: Flag set\n",
dptrs [card]->name);
tpprintf (dptrs [card], DEB_CMDS, "Flag set\n");
di_io (dibptr, ioENF, 0); /* set the flag and recalculate interrupts */
}
@@ -1596,9 +1586,8 @@ t_bool add_word = TRUE;
DI_STATE * const di_card = &di [card];
if (FIFO_FULL) { /* is the FIFO already full? */
if (DEBUG_PRJ (dptrs [card], DEB_BUF))
fprintf (sim_deb, ">>%s buf: Attempted load to full FIFO, data %0*o\n",
dptrs [card]->name, (access == bus_access ? 3 : 6), data);
tpprintf (dptrs [card], DEB_BUF, "Attempted load to full FIFO, data %0*o\n",
(access == bus_access ? 3 : 6), data);
return; /* return with the load ignored */
}
@@ -1665,12 +1654,9 @@ else { /* must be diagnostic ac
if (add_word) /* did we add a word to the FIFO? */
di_card->fifo_count = di_card->fifo_count + 1; /* increment the count of words stored */
if (DEBUG_PRJ (dptrs [card], DEB_BUF)) {
fprintf (sim_deb, ">>%s buf: Data %0*o tag ",
dptrs [card]->name, (access == bus_access ? 3 : 6), data);
fprint_val (sim_deb, tag >> BUS_SHIFT, 2, 4, PV_RZRO);
fprintf (sim_deb, " loaded into FIFO (%d)\n", di_card->fifo_count);
}
tpprintf (dptrs [card], DEB_XFER, "Data %0*o tag %s loaded into FIFO (%d)\n",
(access == bus_access ? 3 : 6), data,
fmt_bitset (tag, tag_format), di_card->fifo_count);
return;
}
@@ -1783,10 +1769,7 @@ t_bool remove_word = TRUE;
DI_STATE * const di_card = &di [card];
if (FIFO_EMPTY) { /* is the FIFO already empty? */
if (DEBUG_PRJ (dptrs [card], DEB_BUF))
fprintf (sim_deb, ">>%s buf: Attempted unload from empty FIFO\n",
dptrs [card]->name);
tpprintf (dptrs [card], DEB_BUF, "Attempted unload from empty FIFO\n");
return 0; /* return with no data */
}
@@ -1838,12 +1821,9 @@ if (remove_word) { /* remove the word from
}
if (DEBUG_PRJ (dptrs [card], DEB_BUF)) {
fprintf (sim_deb, ">>%s buf: Data %0*o tag ",
dptrs [card]->name, (access == cpu_access ? 6 : 3), data);
fprint_val (sim_deb, tag >> BUS_SHIFT, 2, 4, PV_RZRO);
fprintf (sim_deb, " unloaded from FIFO (%d)\n", di_card->fifo_count);
}
tpprintf (dptrs [card], DEB_BUF, "Data %0*o tag %s unloaded from FIFO (%d)\n",
(access == cpu_access ? 6 : 3), data,
fmt_bitset (tag, tag_format), di_card->fifo_count);
if (di_card->cntl_register & CNTL_TALK) /* is the card talking? */
@@ -1867,51 +1847,3 @@ if (di_card->cntl_register & CNTL_TALK) /* is the card talking?
return (uint16) data; /* return the data value */
}
/* Print the bus state for debugging.
The states of the supplied bus control lines are decoded and printed in
mnemonic form to the specified file using the indicated format string. An
asserted bus signal is indicated by its name; a denied signal is omitted.
Implementation notes:
1. The strings in the cntl_names array must appear in BUS_xxx order. The
first element corresponds to bus bit 0, etc.
*/
static void fprint_bus (FILE *file, char *format, uint8 cntl)
{
static const char *cntl_names [] = {
"ATN", /* bit 0: attention */
"EOI", /* bit 1: end or identify */
"DAV", /* bit 2: data available */
"NRFD", /* bit 3: not ready for data */
"NDAC", /* bit 4: not data accepted */
"REN", /* bit 5: remote enable */
"IFC", /* bit 6: interface clear */
"SRQ" /* bit 7: service request */
};
uint32 signal;
char mnemonics [40];
if (cntl == 0) /* are any control signals asserted? */
strcpy (mnemonics, "---"); /* no; use dashes in lieu of an empty string */
else { /* one or more signals are asserted */
mnemonics [0] = '\0';
for (signal = 0; signal <= 7; signal++) /* loop though the set of signals */
if (cntl & (1 << signal)) { /* is this signal asserted? */
if (strlen (mnemonics) > 0) /* yes; is it the first one asserted? */
strcat (mnemonics, " "); /* no, so append a space to separate */
strcat (mnemonics, cntl_names [signal]); /* append the name of the asserted signal */
}
}
fprintf (file, format, mnemonics); /* print the bus state */
return;
}

View File

@@ -25,6 +25,8 @@
DI 12821A Disc Interface
15-Mar-17 JDB Trace flags are now global
09-Mar-17 JDB Changed the DIAG option to DIAGNOSTIC
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
@@ -89,16 +91,6 @@ typedef enum {
#define SET_BUSADR(f) (((f) & UNIT_M_BUSADR) << UNIT_V_BUSADR)
/* Debug flags */
#define DEB_CPU (1 << 0) /* words received from and sent to the CPU */
#define DEB_CMDS (1 << 1) /* interface commands received from the CPU */
#define DEB_BUF (1 << 2) /* data read from and written to the card FIFO */
#define DEB_XFER (1 << 3) /* data received and transmitted via HP-IB */
#define DEB_RWSC (1 << 4) /* device read/write/status/control commands */
#define DEB_SERV (1 << 5) /* unit service scheduling calls */
/* HP-IB control line state bit flags.
NOTE that these flags align with the corresponding flags in the DI status
@@ -140,31 +132,31 @@ typedef enum {
/* 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 */
BYTE_SELECTOR ibp; /* input byte pointer selector */
BYTE_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 */
uint16 input_data_register; /* input data register */
uint16 cntl_register; /* control word register */
uint16 status_register; /* status word register */
uint16 input_data_register; /* input data register */
uint32 fifo [FIFO_SIZE]; /* FIFO buffer */
uint32 fifo_count; /* FIFO occupancy counter */
REG *fifo_reg; /* FIFO register pointer */
uint32 fifo [FIFO_SIZE]; /* FIFO buffer */
uint32 fifo_count; /* FIFO occupancy counter */
REG *fifo_reg; /* FIFO register pointer */
uint32 acceptors; /* unit bitmap of the bus acceptors */
uint32 listeners; /* unit bitmap of the bus listeners */
uint32 talker; /* unit bitmap of the bus talker */
uint32 acceptors; /* unit bitmap of the bus acceptors */
uint32 listeners; /* unit bitmap of the bus listeners */
uint32 talker; /* unit bitmap of the bus talker */
uint8 bus_cntl; /* HP-IB bus control state (ATN, EOI, etc.) */
uint8 poll_response; /* address bitmap of parallel poll responses */
uint8 bus_cntl; /* HP-IB bus control state (ATN, EOI, etc.) */
uint8 poll_response; /* address bitmap of parallel poll responses */
double ifc_timer; /* 100 microsecond IFC timer */
double ifc_timer; /* 100 microsecond IFC timer */
} DI_STATE;
@@ -212,17 +204,17 @@ typedef struct {
These definitions should be included before any device-specific modifiers.
*/
#define DI_MODS(dev) \
{ MTAB_XTD | MTAB_VDV, 1, "ADDRESS", "ADDRESS", &di_set_address, &di_show_address, &dev }, \
\
{ MTAB_XTD | MTAB_VDV, 1, NULL, "DIAG", &di_set_cable, NULL, &dev }, \
{ MTAB_XTD | MTAB_VDV, 0, NULL, "HPIB", &di_set_cable, NULL, &dev }, \
{ MTAB_XTD | MTAB_VDV, 0, "CABLE", NULL, NULL, &di_show_cable, &dev }, \
\
{ MTAB_XTD | MTAB_VDV, 0, "SC", "SC", &hp_setsc, &hp_showsc, &dev }, \
{ MTAB_XTD | MTAB_VDV | MTAB_NMO, 0, "DEVNO", "DEVNO", &hp_setdev, &hp_showdev, &dev }, \
\
{ MTAB_XTD | MTAB_VUN, 0, "BUS", "BUS", &di_set_address, &di_show_address, &dev }
#define DI_MODS(dev,dib) \
{ MTAB_XTD | MTAB_VDV, 1, "ADDRESS", "ADDRESS", &di_set_address, &di_show_address, &dev }, \
\
{ MTAB_XTD | MTAB_VDV, 1, NULL, "DIAGNOSTIC", &di_set_cable, NULL, &dev }, \
{ MTAB_XTD | MTAB_VDV, 0, NULL, "HPIB", &di_set_cable, NULL, &dev }, \
{ MTAB_XTD | MTAB_VDV, 0, "CABLE", NULL, NULL, &di_show_cable, &dev }, \
\
{ MTAB_XTD | MTAB_VDV, 1, "SC", "SC", &hp_set_dib, &hp_show_dib, (void *) &dib }, \
{ MTAB_XTD | MTAB_VDV | MTAB_NMO, ~1u, "DEVNO", "DEVNO", &hp_set_dib, &hp_show_dib, (void *) &dib }, \
\
{ MTAB_XTD | MTAB_VUN, 0, "BUS", "BUS", &di_set_address, &di_show_address, &dev }
/* Disc interface global bus routine definitions */

View File

@@ -25,6 +25,10 @@
DA 12821A Disc Interface with Amigo disc drives
11-Jul-17 JDB Renamed "ibl_copy" to "cpu_ibl"
15-Mar-17 JDB Changed DEBUG_PRI calls to tprintfs
09-Mar-17 JDB Deprecated LOCKED/WRITEENABLED for PROTECT/UNPROTECT
27-Feb-17 JDB ibl_copy no longer returns a status code
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
@@ -345,6 +349,7 @@
#include "hp2100_defs.h"
#include "hp2100_cpu.h"
#include "hp2100_di.h"
#include "hp2100_disclib.h"
@@ -553,20 +558,25 @@ REG da_reg [] = {
};
MTAB da_mod [] = {
DI_MODS (da_dev),
DI_MODS (da_dev, da_dib),
{ UNIT_UNLOAD, UNIT_UNLOAD, "heads unloaded", "UNLOADED", &da_load_unload, NULL, NULL },
{ UNIT_UNLOAD, 0, "heads loaded", "LOADED", &da_load_unload, NULL, NULL },
/* Mask Value Match Value Print String Match String Validation Display Descriptor */
/* ------------ ------------ ----------------- --------------- ---------------- ------- ---------- */
{ UNIT_UNLOAD, UNIT_UNLOAD, "heads unloaded", "UNLOADED", &da_load_unload, NULL, NULL },
{ UNIT_UNLOAD, 0, "heads loaded", "LOADED", &da_load_unload, NULL, NULL },
{ UNIT_WLK, UNIT_WLK, "write locked", "LOCKED", NULL, NULL, NULL },
{ UNIT_WLK, 0, "write enabled", "WRITEENABLED", NULL, NULL, NULL },
{ UNIT_WLK, UNIT_WLK, "protected", "PROTECT", NULL, NULL, NULL },
{ UNIT_WLK, 0, "unprotected", "UNPROTECT", NULL, NULL, NULL },
{ UNIT_FMT, UNIT_FMT, "format enabled", "FORMAT", NULL, NULL, NULL },
{ UNIT_FMT, 0, "format disabled", "NOFORMAT", NULL, NULL, NULL },
{ UNIT_WLK, UNIT_WLK, NULL, "LOCKED", NULL, NULL, NULL },
{ UNIT_WLK, 0, NULL, "WRITEENABLED", NULL, NULL, NULL },
{ UNIT_MODEL, MODEL_7906, "7906H", "7906H", &dl_set_model, NULL, NULL },
{ UNIT_MODEL, MODEL_7920, "7920H", "7920H", &dl_set_model, NULL, NULL },
{ UNIT_MODEL, MODEL_7925, "7925H", "7925H", &dl_set_model, NULL, NULL },
{ UNIT_FMT, UNIT_FMT, "format enabled", "FORMAT", NULL, NULL, NULL },
{ UNIT_FMT, 0, "format disabled", "NOFORMAT", NULL, NULL, NULL },
{ UNIT_MODEL, MODEL_7906, "7906H", "7906H", &dl_set_model, NULL, NULL },
{ UNIT_MODEL, MODEL_7920, "7920H", "7920H", &dl_set_model, NULL, NULL },
{ UNIT_MODEL, MODEL_7925, "7925H", "7925H", &dl_set_model, NULL, NULL },
{ 0 }
};
@@ -807,9 +817,8 @@ switch (if_state [unit]) { /* dispatch the inte
if_state [unit] = read_xfer; /* we are ready to transfer the data */
uptr->wait = cvptr->cmd_time; /* schedule the transfer */
if (DEBUG_PRI (da_dev, DEB_RWSC))
fprintf (sim_deb, ">>DA rwsc: Unit %d Amigo identify response %04XH\n",
unit, buffer [0]);
tprintf (da_dev, DEB_RWSC, "Unit %d Amigo identify response %04XH\n",
unit, buffer [0]);
break;
@@ -967,36 +976,31 @@ switch (if_state [unit]) { /* dispatch the inte
if (uptr->wait) /* is service requested? */
activate_unit (uptr); /* schedule the next event */
if (result == SCPE_IERR && DEBUG_PRI (da_dev, DEB_RWSC)) { /* did an internal error occur? */
fprintf (sim_deb, ">>DA rwsc: Unit %d ", unit); /* report it if debugging */
if (result == SCPE_IERR) /* did an internal error occur? */
if (if_state [unit] == command_exec
&& if_command [unit] == disc_command)
fprintf (sim_deb, "%s command %s phase ",
tprintf (da_dev, DEB_RWSC, "Unit %d %s command %s phase service not handled\n",
unit,
dl_opcode_name (ICD, (CNTLR_OPCODE) uptr->OP),
dl_phase_name ((CNTLR_PHASE) uptr->PHASE));
else
fprintf (sim_deb, "%s state %s ",
tprintf (da_dev, DEB_RWSC, "Unit %d %s state %s service not handled\n",
unit,
if_command_name [if_command [unit]],
if_state_name [if_state [unit]]);
fputs ("service not handled\n", sim_deb);
}
if (if_state [unit] == idle) { /* is the command now complete? */
if (if_command [unit] == disc_command) { /* did a disc command complete? */
if (cvptr->opcode != End) /* yes; if the command was not End, */
di_poll_response (da, unit, SET); /* then enable PPR */
if (DEBUG_PRI (da_dev, DEB_RWSC))
fprintf (sim_deb, ">>DA rwsc: Unit %d %s disc command completed\n",
unit, dl_opcode_name (ICD, cvptr->opcode));
tprintf (da_dev, DEB_RWSC, "Unit %d %s disc command completed\n",
unit, dl_opcode_name (ICD, cvptr->opcode));
}
else /* an interface command completed */
if (DEBUG_PRI (da_dev, DEB_RWSC))
fprintf (sim_deb, ">>DA rwsc: Unit %d %s command completed\n",
unit, if_command_name [if_command [unit]]);
tprintf (da_dev, DEB_RWSC, "Unit %d %s command completed\n",
unit, if_command_name [if_command [unit]]);
if (release_interface) /* if the next command is already pending */
di_bus_control (da, unit, 0, BUS_NRFD); /* deny NRFD to allow the card to resume */
@@ -1214,15 +1218,14 @@ static const BOOT_ROM da_rom = {
t_stat da_boot (int32 unitno, DEVICE *dptr)
{
if (GET_BUSADR (da_unit [unitno].flags) != 0) /* booting is supported on bus address 0 only */
return SCPE_NOFNC; /* report "Command not allowed" if attempted */
if (GET_BUSADR (da_unit [unitno].flags) != 0) /* booting is supported on bus address 0 only */
return SCPE_NOFNC; /* report "Command not allowed" if attempted */
if (ibl_copy (da_rom, da_dib.select_code, /* copy the boot ROM to memory and configure */
IBL_OPT | IBL_DS_HEAD, /* the S register accordingly */
IBL_DS | IBL_MAN | IBL_SET_SC (da_dib.select_code)))
return SCPE_IERR; /* return an internal error if the copy failed */
else
return SCPE_OK;
cpu_ibl (da_rom, da_dib.select_code, /* copy the boot ROM to memory and configure */
IBL_OPT | IBL_DS_HEAD, /* the S register accordingly */
IBL_DS | IBL_MAN | IBL_SET_SC (da_dib.select_code));
return SCPE_OK;
}
@@ -1451,8 +1454,7 @@ if (di [da].bus_cntl & BUS_ATN) { /* is it a bus comma
case 0x04: /* selected device clear */
case 0x05: /* SDC with parity freeze */
case 0x14: /* universal clear */
if (DEBUG_PRI (da_dev, DEB_RWSC))
fprintf (sim_deb, ">>DA rwsc: Unit %d device cleared\n", unit);
tprintf (da_dev, DEB_RWSC, "Unit %d device cleared\n", unit);
sim_cancel (&da_unit [unit]); /* cancel any in-progress command */
dl_idle_controller (&icd_cntlr [unit]); /* idle the controller */
@@ -1460,7 +1462,7 @@ if (di [da].bus_cntl & BUS_ATN) { /* is it a bus comma
if_state [unit] = idle; /* idle the interface */
di_poll_response (da, unit, SET); /* enable PPR */
if (DEBUG_PRI (da_dev, DEB_XFER))
if (TRACING (da_dev, DEB_XFER))
strcpy (action, "device clear");
break;
@@ -1482,7 +1484,7 @@ if (di [da].bus_cntl & BUS_ATN) { /* is it a bus comma
addressed = TRUE; /* unit is now addressed */
stopped_talking = TRUE; /* MLA stops the unit from talking */
if (DEBUG_PRI (da_dev, DEB_XFER))
if (TRACING (da_dev, DEB_XFER))
sprintf (action, "listen %d", message_address);
}
@@ -1491,7 +1493,7 @@ if (di [da].bus_cntl & BUS_ATN) { /* is it a bus comma
stopped_listening = TRUE; /* UNL stops the unit from listening */
if (DEBUG_PRI (da_dev, DEB_XFER))
if (TRACING (da_dev, DEB_XFER))
strcpy (action, "unlisten");
}
@@ -1511,7 +1513,7 @@ if (di [da].bus_cntl & BUS_ATN) { /* is it a bus comma
addressed = TRUE; /* the unit is now addressed */
stopped_listening = TRUE; /* MTA stops the unit from listening */
if (DEBUG_PRI (da_dev, DEB_XFER))
if (TRACING (da_dev, DEB_XFER))
sprintf (action, "talk %d", message_address);
}
@@ -1524,7 +1526,7 @@ if (di [da].bus_cntl & BUS_ATN) { /* is it a bus comma
accepted = FALSE; /* are not accepted */
else /* it's an Untalk */
if (DEBUG_PRI (da_dev, DEB_XFER))
if (TRACING (da_dev, DEB_XFER))
strcpy (action, "untalk");
}
@@ -1670,7 +1672,7 @@ if (di [da].bus_cntl & BUS_ATN) { /* is it a bus comma
if (accepted) { /* was the command accepted? */
if (DEBUG_PRI (da_dev, DEB_XFER))
if (TRACING (da_dev, DEB_XFER))
sprintf (action, "secondary %02XH", message_address);
if (if_command [unit] != amigo_identify) /* disable PPR for all commands */
@@ -1685,8 +1687,7 @@ if (di [da].bus_cntl & BUS_ATN) { /* is it a bus comma
if_state [unit] = command_wait; /* change the interface state to wait */
di_bus_control (da, unit, BUS_NRFD, 0); /* and assert NRFD to hold off the card */
if (DEBUG_PRI (da_dev, DEB_RWSC))
fprintf (sim_deb, ">>DA rwsc: Unit %d addressed while controller is busy\n", unit);
tprintf (da_dev, DEB_RWSC, "Unit %d addressed while controller is busy\n", unit);
}
if (stopped_listening) { /* was the unit Unlistened? */
@@ -1715,7 +1716,7 @@ else { /* it is bus data (A
switch (if_state [unit]) { /* dispatch the interface state */
case opcode_wait: /* waiting for an opcode */
if (DEBUG_PRI (da_dev, DEB_XFER))
if (TRACING (da_dev, DEB_XFER))
sprintf (action, "opcode %02XH", data & DL_OPCODE_MASK);
buffer [0] = TO_WORD (data, 0); /* set the opcode into the buffer */
@@ -1737,7 +1738,7 @@ else { /* it is bus data (A
case parameter_wait: /* waiting for a parameter */
if (DEBUG_PRI (da_dev, DEB_XFER))
if (TRACING (da_dev, DEB_XFER))
sprintf (action, "parameter %02XH", data);
put_buffer_byte (&icd_cntlr [unit], data); /* add the byte to the buffer */
@@ -1761,7 +1762,7 @@ else { /* it is bus data (A
/* fall into error_sink handler */
case error_sink: /* sinking data after an error */
if (DEBUG_PRI (da_dev, DEB_XFER))
if (TRACING (da_dev, DEB_XFER))
sprintf (action, "data %03o", data);
if (di [da].bus_cntl & BUS_EOI) /* is this the last byte from the bus? */
@@ -1777,26 +1778,26 @@ else { /* it is bus data (A
abort_command (unit, io_program_error, /* report the error */
error_sink); /* and sink any data that follows */
if (DEBUG_PRI (da_dev, DEB_XFER))
if (TRACING (da_dev, DEB_XFER))
sprintf (action, "unhandled data %03o", data);
break;
}
}
if (accepted && DEBUG_PRI (da_dev, DEB_XFER))
fprintf (sim_deb, ">>DA xfer: HP-IB address %d accepted %s\n",
if (accepted)
tprintf (da_dev, DEB_XFER, "HP-IB address %d accepted %s\n",
GET_BUSADR (da_unit [unit].flags), action);
if (da_unit [unit].wait > 0) /* was service requested? */
activate_unit (&da_unit [unit]); /* schedule the unit */
if (initiated && DEBUG_PRI (da_dev, DEB_RWSC))
if (initiated)
if (if_command [unit] == disc_command)
fprintf (sim_deb, ">>DA rwsc: Unit %d position %" T_ADDR_FMT "d %s disc command initiated\n",
tprintf (da_dev, DEB_RWSC, "Unit %d position %" T_ADDR_FMT "d %s disc command initiated\n",
unit, da_unit [unit].pos, dl_opcode_name (ICD, icd_cntlr [unit].opcode));
else
fprintf (sim_deb, ">>DA rwsc: Unit %d %s command initiated\n",
tprintf (da_dev, DEB_RWSC, "Unit %d %s command initiated\n",
unit, if_command_name [if_command [unit]]);
return accepted; /* indicate the acceptance condition */
@@ -2123,15 +2124,10 @@ return;
static t_stat activate_unit (UNIT *uptr)
{
int32 unit;
t_stat result;
if (DEBUG_PRI (da_dev, DEB_SERV)) {
unit = uptr - da_unit;
fprintf (sim_deb, ">>DA serv: Unit %d state %s delay %d service scheduled\n",
unit, if_state_name [if_state [unit]], uptr->wait);
}
tprintf (da_dev, DEB_SERV, "Unit %d state %s delay %d service scheduled\n",
uptr - da_unit, if_state_name [if_state [uptr - da_unit]], uptr->wait);
result = sim_activate (uptr, uptr->wait); /* activate the unit */
uptr->wait = 0; /* reset the activation time */

View File

@@ -1,6 +1,6 @@
SIMH/HP 21XX DIAGNOSTICS PERFORMANCE
====================================
Last update: 2016-12-18
Last update: 2017-02-15
The HP 24396 diagnostic suite has been run against the SIMH HP 21xx simulation.
@@ -84,7 +84,7 @@ The results of the diagnostic runs are summarized below:
105000 2610/14 Line Printer 1451 - No simulation
105101 2767 Line Printer 1611 3.3-0 Passed
105102 2607 Line Printer 1446 3.3-0 Passed
145103 2613/17/18 Line Printer 1633 - No simulation
145103 2613/17/18 Line Printer 1633 4.0-0 Passed
105104 9866 Line Printer 1541 - No simulation
105106 2631 Printer 1913 - No simulation
105107 2635 Printing Terminal 1913 - No simulation
@@ -1064,7 +1064,7 @@ DSN 103115 - Privileged Interrupt
TESTED DEVICE: PIF (hp2100_pif.c)
CONFIGURATION: sim> set PIF 12936A
sim> set LPT DEV=44
sim> set LPT SC=44
sim> deposit S 004414
sim> reset
@@ -1596,12 +1596,12 @@ DSN 105102 - 2607 Line Printer
TESTED DEVICE: LPT (hp2100_lpt.c)
CONFIGURATION: sim> attach LPT scratch.2607.printer
CONFIGURATION: sim> attach -n LPT scratch.2607.printer
sim> deposit S 100015
sim> reset
sim> go 100
HALT instruction 102074
Programmed halt, T: 102074 (HLT 74)
sim> deposit S 001000
sim> reset
@@ -1609,7 +1609,7 @@ CONFIGURATION: sim> attach LPT scratch.2607.printer
2607 LINE PRINTER DIAGNOSTIC
HALT instruction 102075
Programmed halt, T: 102075 (HLT 75)
sim> deposit A 000377
sim> deposit S 000000
@@ -1618,7 +1618,7 @@ CONFIGURATION: sim> attach LPT scratch.2607.printer
TEST REPORT: H024 PRESS PRESET (EXT&INT),RUN
HALT instruction 102024
Programmed halt, T: 102024 (HLT 24)
sim> reset
sim> go
@@ -1626,63 +1626,63 @@ TEST REPORT: H024 PRESS PRESET (EXT&INT),RUN
H025 BI-O COMP
H040 PWR OFF LP,PRESS RUN
HALT instruction 102040
Programmed halt, T: 102040 (HLT 40)
sim> set LPT poweroff
sim> set LPT POWEROFF
sim> go
H041 PWR ON LP,READY LP,PRESS RUN
HALT instruction 102041
Programmed halt, T: 102041 (HLT 41)
sim> set LPT poweron
sim> set LPT POWERON
sim> go
H042 PRINT SW OFF,PRESS RUN
HALT instruction 102042
Programmed halt, T: 102042 (HLT 42)
sim> set LPT offline
sim> set LPT OFFLINE
sim> go
H043 PRINT SW ON,PRESS RUN
HALT instruction 102043
Programmed halt, T: 102043 (HLT 43)
sim> set LPT online
sim> set LPT ONLINE
sim> go
H044 OPEN PLATEN,PRESS RUN
HALT instruction 102044
Programmed halt, T: 102044 (HLT 44)
sim> set LPT offline
sim> set LPT OFFLINE
sim> go
H045 CLOSE PLATEN,PRESS RUN
HALT instruction 102045
Programmed halt, T: 102045 (HLT 45)
sim> set LPT online
sim> set LPT ONLINE
sim> go
H046 REMOVE PAPER FROM LP,PRESS RUN
HALT instruction 102046
Programmed halt, T: 102046 (HLT 46)
sim> detach LPT
sim> go
H047 RESTORE PAPER IN LP, READY LP,PRESS RUN
HALT instruction 102047
Programmed halt, T: 102047 (HLT 47)
sim> attach LPT scratch.2607.printer
sim> go
PASS 000001
HALT instruction 102077
Programmed halt, T: 102077 (HLT 77)
TEST RESULT: Passed.
@@ -1692,6 +1692,90 @@ TEST NOTES: The standard tests 00-07 are executed. Test 08 (operator
------------------------------------
DSN 145103 - 2613/17/18 Line Printer
------------------------------------
TESTED DEVICE: LPT (hp2100_lpt.c)
CONFIGURATION: sim> set LPT 2613,DIAGNOSTIC
sim> attach -n LPT scratch.2613.printer
sim> deposit S 000015
sim> reset
sim> go 100
Programmed halt, T: 102074 (HLT 74)
sim> deposit S 000000
sim> reset
sim> go
TEST REPORT: 2613-2618 LINE PRINTER DIAG
H024 PRESS PRESET (EXT&INT),RUN
Programmed halt, T: 102024 (HLT 24)
sim> reset
sim> go
H025 BI-O COMP
H040 PWR OFF LP,PRESS RUN
Programmed halt, T: 102040 (HLT 40)
sim> set LPT POWEROFF
sim> go
H041 PWR ON, ON LINE LP,PRESS RUN
Programmed halt, T: 102041 (HLT 41)
sim> set LPT POWERON
sim> go
H042 LP TO OFF LINE,PRESS RUN
Programmed halt, T: 102042 (HLT 42)
sim> set LPT OFFLINE
sim> go
H043 LP TO ON LINE,PRESS RUN
Programmed halt, T: 102043 (HLT 43)
sim> set LPT ONLINE
sim> go
H044 OPEN DRUM GATE,PRESS RUN
Programmed halt, T: 102044 (HLT 44)
sim> detach LPT
sim> go
H046 REMOVE PAPER,CLOSE DRUM GATE,PRESS RUN
Programmed halt, T: 102046 (HLT 46)
sim> go
H047 RESTORE PAPER, ON LINE LP, PRESS RUN
Programmed halt, T: 102047 (HLT 47)
sim> attach LPT scratch.2613.printer
sim> set LPT ONLINE
sim> go
PASS 000001
Programmed halt, T: 102077 (HLT 77)
TEST RESULT: Passed.
-----------------------------------------------------
DSN 111001 - HP2100A Disc File (2883) (multiple unit)
-----------------------------------------------------

View File

@@ -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.
03-Aug-17 JDB Changed perror call for I/O errors to cprintf
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"
@@ -2279,8 +2280,10 @@ static t_stat io_error (CVPTR cvptr, UNIT *uptr, CNTLR_STATUS status)
{
dl_end_command (cvptr, status); /* terminate the command with an error */
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 */
cprintf ("%s simulator disc library I/O error: %s\n", /* report the error to the console */
sim_name, strerror (errno));
clearerr (uptr->fileref); /* clear the error */
return SCPE_IOERR; /* return an I/O error to stop the simulator */
}

View File

@@ -1,33 +1,37 @@
/* hp2100_dp.c: HP 2100 12557A/13210A disk simulator
/* hp2100_dp.c: HP 2100 12557A/13210A disc 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"),
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
AUTHORS 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.
DP 12557A 2870 disk subsystem
13210A 7900 disk subsystem
DP 12557A 2870 disc subsystem
13210A 7900 disc subsystem
03-Aug-17 JDB Changed perror call for I/O errors to cprintf
11-Jul-17 JDB Renamed "ibl_copy" to "cpu_ibl"
22-Apr-17 JDB Added fall-through comment for FNC_STA case in dpcio
09-Mar-17 JDB Deprecated LOCKED/WRITEENABLED for PROTECT/UNPROTECT
27-Feb-17 JDB ibl_copy no longer returns a status code
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
@@ -75,11 +79,12 @@
21-Nov-00 RMS Fixed flag, buffer power up state
References:
- 7900A Disc Drive Operating and Service Manual (07900-90002, Feb-1975)
- 13210A Disc Drive Interface Kit Operating and Service Manual
(13210-90003, Nov-1974)
- 12557A Cartridge Disc Interface Kit Operating and Service Manual
(12557-90001, Sep-1970)
- 7900A Disc Drive Operating and Service Manual
(07900-90002, February 1975)
- 13210A Disc Drive Interface Kit Operating and Service Manual
(13210-90003, November 1974)
- 12557A Cartridge Disc Interface Kit Operating and Service Manual
(12557-90001, Sepember 1970)
The simulator uses a number of state variables:
@@ -127,7 +132,12 @@
2. Omitting STC DC before Status Check does not set DC flag but does poll.
*/
#include "hp2100_defs.h"
#include "hp2100_cpu.h"
#define UNIT_V_WLK (UNIT_V_UF + 0) /* write locked */
#define UNIT_V_UNLOAD (UNIT_V_UF + 1) /* heads unloaded */
@@ -311,9 +321,11 @@ REG dpd_reg[] = {
{ NULL }
};
MTAB dpd_mod[] = {
{ MTAB_XTD | MTAB_VDV, 1, "SC", "SC", &hp_setsc, &hp_showsc, &dpd_dev },
{ MTAB_XTD | MTAB_VDV | MTAB_NMO, 1, "DEVNO", "DEVNO", &hp_setdev, &hp_showdev, &dpd_dev },
MTAB dpd_mod [] = {
/* Entry Flags Value Print String Match String Validation Display Descriptor */
/* ------------------- ----- ------------ ------------ ------------ ------------- ---------------- */
{ MTAB_XDV, 2u, "SC", "SC", &hp_set_dib, &hp_show_dib, (void *) &dp_dib },
{ MTAB_XDV | MTAB_NMO, ~2u, "DEVNO", "DEVNO", &hp_set_dib, &hp_show_dib, (void *) &dp_dib },
{ 0 }
};
@@ -373,19 +385,23 @@ 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",
&dp_settype, NULL, NULL },
{ MTAB_XTD | MTAB_VDV, 0, NULL, "12557A",
&dp_settype, NULL, NULL },
{ MTAB_XTD | MTAB_VDV, 0, "TYPE", NULL,
NULL, &dp_showtype, NULL },
{ MTAB_XTD | MTAB_VDV, 1, "SC", "SC", &hp_setsc, &hp_showsc, &dpd_dev },
{ MTAB_XTD | MTAB_VDV | MTAB_NMO, 1, "DEVNO", "DEVNO", &hp_setdev, &hp_showdev, &dpd_dev },
MTAB dpc_mod [] = {
/* Mask Value Match Value Print String Match String Validation Display Descriptor */
/* ------------ ------------ ----------------- --------------- ----------------- ------- ---------- */
{ UNIT_UNLOAD, UNIT_UNLOAD, "heads unloaded", "UNLOADED", &dpc_load_unload, NULL, NULL },
{ UNIT_UNLOAD, 0, "heads loaded", "LOADED", &dpc_load_unload, NULL, NULL },
{ UNIT_WLK, UNIT_WLK, "protected", "PROTECT", NULL, NULL, NULL },
{ UNIT_WLK, 0, "unprotected", "UNPROTECT", NULL, NULL, NULL },
{ UNIT_WLK, UNIT_WLK, NULL, "LOCKED", NULL, NULL, NULL },
{ UNIT_WLK, 0, NULL, "WRITEENABLED", NULL, NULL, NULL },
/* Entry Flags Value Print String Match String Validation Display Descriptor */
/* ------------------- ----- ------------ ------------ ------------ ------------- ---------------- */
{ MTAB_XDV, 1, NULL, "13210A", &dp_settype, NULL, NULL },
{ MTAB_XDV, 0, NULL, "12557A", &dp_settype, NULL, NULL },
{ MTAB_XDV, 0, "TYPE", NULL, NULL, &dp_showtype, NULL },
{ MTAB_XDV, 2u, "SC", "SC", &hp_set_dib, &hp_show_dib, (void *) &dp_dib },
{ MTAB_XDV | MTAB_NMO, ~2u, "DEVNO", "DEVNO", &hp_set_dib, &hp_show_dib, (void *) &dp_dib },
{ 0 }
};
@@ -997,8 +1013,10 @@ dpc_busy = 0; /* ctlr is free */
dpd_xfer = dpd_wval = 0;
if (err != 0) { /* error? */
perror ("DP I/O error");
clearerr (uptr->fileref);
cprintf ("%s simulator DP disc I/O error: %s\n", /* then report the error to the console */
sim_name, strerror (errno));
clearerr (uptr->fileref); /* clear the error */
return SCPE_IOERR;
}
return SCPE_OK;
@@ -1195,10 +1213,9 @@ const int32 dev = dpd_dib.select_code; /* data chan select code
if (unitno != 0) /* boot supported on drive unit 0 only */
return SCPE_NOFNC; /* report "Command not allowed" if attempted */
if (ibl_copy (dp_rom, dev, IBL_OPT, /* copy the boot ROM to memory and configure */
IBL_DP | IBL_SET_SC (dev) /* the S register accordingly */
| (sim_switches & SWMASK ('R') ? IBL_DP_REM : 0)))
return SCPE_IERR; /* return an internal error if the copy failed */
else
return SCPE_OK;
cpu_ibl (dp_rom, dev, IBL_OPT, /* copy the boot ROM to memory and configure */
IBL_DP | IBL_SET_SC (dev) /* the S register accordingly */
| (sim_switches & SWMASK ('R') ? IBL_DP_REM : 0));
return SCPE_OK;
}

View File

@@ -1,31 +1,35 @@
/* hp2100_dq.c: HP 2100 12565A disk simulator
/* hp2100_dq.c: HP 2100 12565A Disc Interface and 2883 disc drive simulator
Copyright (c) 1993-2006, Bill McDermith
Copyright (c) 2004-2016 J. David Bryan
Copyright (c) 2004-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
AUTHORS 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 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 the authors.
DQ 12565A 2883 disk system
DQ 12565A Disc Interface and 2883 disc drive
03-Aug-17 JDB Changed perror call for I/O errors to cprintf
11-Jul-17 JDB Renamed "ibl_copy" to "cpu_ibl"
09-Mar-17 JDB Deprecated LOCKED/WRITEENABLED for PROTECT/UNPROTECT
27-Feb-17 JDB ibl_copy no longer returns a status code
13-May-16 JDB Modified for revised SCP API function parameter types
30-Dec-14 JDB Added S-register parameters to ibl_copy
24-Dec-14 JDB Added casts for explicit downward conversions
@@ -52,10 +56,11 @@
09-Jan-02 WOM Copied dp driver and mods for 2883
Reference:
- 12565A Disc Interface Kit Operating and Service Manual (12565-90003, Aug-1973)
- 12565A Disc Interface Kit Operating and Service Manual
(12565-90003, August 1973)
Differences between 12559/13210 and 12565 controllers
Differences between 12559/13210 and 12565 controllers:
- 12565 stops transfers on address miscompares; 12559/13210 only stops writes
- 12565 does not set error on positioner busy
- 12565 does not set positioner busy if already on cylinder
@@ -82,7 +87,12 @@
1. Read Address command starts at the sector number in the RAR.
*/
#include "hp2100_defs.h"
#include "hp2100_cpu.h"
#define UNIT_V_WLK (UNIT_V_UF + 0) /* write locked */
#define UNIT_V_UNLOAD (UNIT_V_UF + 1) /* heads unloaded */
@@ -234,9 +244,11 @@ REG dqd_reg[] = {
{ NULL }
};
MTAB dqd_mod[] = {
{ MTAB_XTD | MTAB_VDV, 1, "SC", "SC", &hp_setsc, &hp_showsc, &dqd_dev },
{ MTAB_XTD | MTAB_VDV | MTAB_NMO, 1, "DEVNO", "DEVNO", &hp_setdev, &hp_showdev, &dqd_dev },
MTAB dqd_mod [] = {
/* Entry Flags Value Print String Match String Validation Display Descriptor */
/* ------------------- ----- ------------ ------------ ------------ ------------- ---------------- */
{ MTAB_XDV, 2u, "SC", "SC", &hp_set_dib, &hp_show_dib, (void *) &dq_dib },
{ MTAB_XDV | MTAB_NMO, ~2u, "DEVNO", "DEVNO", &hp_set_dib, &hp_show_dib, (void *) &dq_dib },
{ 0 }
};
@@ -288,13 +300,20 @@ 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, "SC", "SC", &hp_setsc, &hp_showsc, &dqd_dev },
{ MTAB_XTD | MTAB_VDV | MTAB_NMO, 1, "DEVNO", "DEVNO", &hp_setdev, &hp_showdev, &dqd_dev },
MTAB dqc_mod [] = {
/* Mask Value Match Value Print String Match String Validation Display Descriptor */
/* ------------ ------------ ----------------- --------------- ----------------- ------- ---------- */
{ UNIT_UNLOAD, UNIT_UNLOAD, "heads unloaded", "UNLOADED", &dqc_load_unload, NULL, NULL },
{ UNIT_UNLOAD, 0, "heads loaded", "LOADED", &dqc_load_unload, NULL, NULL },
{ UNIT_WLK, UNIT_WLK, "protected", "PROTECT", NULL, NULL, NULL },
{ UNIT_WLK, 0, "unprotected", "UNPROTECT", NULL, NULL, NULL },
{ UNIT_WLK, UNIT_WLK, NULL, "LOCKED", NULL, NULL, NULL },
{ UNIT_WLK, 0, NULL, "WRITEENABLED", NULL, NULL, NULL },
/* Entry Flags Value Print String Match String Validation Display Descriptor */
/* ------------------- ----- ------------ ------------ ------------ ------------- ---------------- */
{ MTAB_XDV, 2u, "SC", "SC", &hp_set_dib, &hp_show_dib, (void *) &dq_dib },
{ MTAB_XDV | MTAB_NMO, ~2u, "DEVNO", "DEVNO", &hp_set_dib, &hp_show_dib, (void *) &dq_dib },
{ 0 }
};
@@ -821,8 +840,10 @@ dqcio (&dqc_dib, ioENF, 0); /* set cch flg */
dqc_busy = 0; /* ctlr is free */
dqd_xfer = dqd_wval = 0;
if (err != 0) { /* error? */
perror ("DQ I/O error");
clearerr (uptr->fileref);
cprintf ("%s simulator DQ disc I/O error: %s\n", /* then report the error to the console */
sim_name, strerror (errno));
clearerr (uptr->fileref); /* clear the error */
return SCPE_IOERR;
}
return SCPE_OK;
@@ -970,9 +991,8 @@ const int32 dev = dqd_dib.select_code; /* data chan select code
if (unitno != 0) /* boot supported on drive unit 0 only */
return SCPE_NOFNC; /* report "Command not allowed" if attempted */
if (ibl_copy (dq_rom, dev, IBL_OPT, /* copy the boot ROM to memory and configure */
IBL_DQ | IBL_SET_SC (dev))) /* the S register accordingly */
return SCPE_IERR; /* return an internal error if the copy failed */
else
return SCPE_OK;
cpu_ibl (dq_rom, dev, IBL_OPT, /* copy the boot ROM to memory and configure */
IBL_DQ | IBL_SET_SC (dev)); /* the S register accordingly */
return SCPE_OK;
}

View File

@@ -1,31 +1,35 @@
/* hp2100_dr.c: HP 2100 12606B/12610B fixed head disk/drum 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"),
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
AUTHORS 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.
DR 12606B 2770/2771 fixed head disk
12610B 2773/2774/2775 drum
19-Jul-17 JDB Removed "dr_stopioe" variable and register
11-Jul-17 JDB Renamed "ibl_copy" to "cpu_ibl"
27-Feb-17 JDB ibl_copy no longer returns a status code
10-Nov-16 JDB Modified the drc_boot routine to use the BBDL
05-Aug-16 JDB Renamed the P register from "PC" to "PR"
13-May-16 JDB Modified for revised SCP API function parameter types
@@ -109,10 +113,14 @@
- inst timing = 6 inst/word, 12288 inst/revolution
*/
#include "hp2100_defs.h"
#include "hp2100_cpu.h"
#include <math.h>
/* Constants */
#define DR_NUMWD 64 /* words/sector */
@@ -195,7 +203,6 @@ int32 drd_ibuf = 0; /* input buffer */
int32 drd_obuf = 0; /* output buffer */
int32 drd_ptr = 0; /* sector pointer */
int32 drc_pcount = 1; /* number of prot tracks */
int32 dr_stopioe = 1; /* stop on error */
int32 dr_time = DR_DTIME; /* time per word */
static int32 sz_tab[16] = {
@@ -252,8 +259,8 @@ REG drd_reg[] = {
};
MTAB drd_mod[] = {
{ MTAB_XTD | MTAB_VDV, 1, "SC", "SC", &hp_setsc, &hp_showsc, &drd_dev },
{ MTAB_XTD | MTAB_VDV | MTAB_NMO, 1, "DEVNO", "DEVNO", &hp_setdev, &hp_showdev, &drd_dev },
{ MTAB_XTD | MTAB_VDV, 2u, "SC", "SC", &hp_set_dib, &hp_show_dib, (void *) &dr_dib },
{ MTAB_XTD | MTAB_VDV | MTAB_NMO, ~2u, "DEVNO", "DEVNO", &hp_set_dib, &hp_show_dib, (void *) &dr_dib },
{ 0 }
};
@@ -284,7 +291,6 @@ REG drc_reg[] = {
{ ORDATA (STA, drc_sta, 16) },
{ FLDATA (RUN, drc_run, 0) },
{ DRDATA (TIME, dr_time, 24), REG_NZ + PV_LEFT },
{ FLDATA (STOP_IOE, dr_stopioe, 0) },
{ ORDATA (SC, drc_dib.select_code, 6), REG_HRO },
{ ORDATA (DEVNO, drc_dib.select_code, 6), REG_HRO },
{ DRDATA (CAPAC, drc_unit.capac, 24), REG_HRO },
@@ -308,8 +314,8 @@ MTAB drc_mod[] = {
{ UNIT_PROT, 0, "unprotected", "UNPROTECTED", NULL },
{ MTAB_XTD | MTAB_VDV, 0, "TRACKPROT", "TRACKPROT",
&dr_set_prot, &dr_show_prot, NULL },
{ MTAB_XTD | MTAB_VDV, 1, "SC", "SC", &hp_setsc, &hp_showsc, &drd_dev },
{ MTAB_XTD | MTAB_VDV | MTAB_NMO, 1, "DEVNO", "DEVNO", &hp_setdev, &hp_showdev, &drd_dev },
{ MTAB_XTD | MTAB_VDV, 2u, "SC", "SC", &hp_set_dib, &hp_show_dib, (void *) &dr_dib },
{ MTAB_XTD | MTAB_VDV | MTAB_NMO, ~2u, "DEVNO", "DEVNO", &hp_set_dib, &hp_show_dib, (void *) &dr_dib },
{ 0 }
};
@@ -522,7 +528,7 @@ uint16 *bptr = (uint16 *) uptr->filebuf;
if ((uptr->flags & UNIT_ATT) == 0) {
drc_sta = DRS_ABO;
return IOERROR (dr_stopioe, SCPE_UNATT);
return SCPE_OK;
}
trk = CW_GETTRK (drc_cw);
@@ -723,7 +729,7 @@ return SCPE_OK;
In hardware, the BBDL was hand-configured for the disc and paper tape reader
select codes when it was installed on a given system. Under simulation, we
treat it as a standard HP 1000 loader, even though it is not structured that
way, and so the ibl_copy mechanism used to load and configure it must be
way, and so the cpu_ibl mechanism used to load and configure it must be
augmented to account for the differences.
@@ -732,7 +738,7 @@ return SCPE_OK;
1. The full BBDL is loaded into memory, even though only the disc portion
will be used.
2. For compatibility with the ibl_copy routine, the loader has been changed
2. For compatibility with the cpu_ibl routine, the loader has been changed
from the standard HP version. The device I/O instructions are modified
to address locations 10 and 11.
*/
@@ -811,19 +817,18 @@ static const BOOT_ROM dr_rom = {
t_stat drc_boot (int32 unitno, DEVICE *dptr)
{
const int32 dev = drd_dib.select_code; /* data chan select code */
const HP_WORD dev = (HP_WORD) drd_dib.select_code; /* data chan select code */
if (unitno != 0) /* boot supported on drive unit 0 only */
return SCPE_NOFNC; /* report "Command not allowed" if attempted */
if (ibl_copy (dr_rom, dev, IBL_S_NOCLR, IBL_S_NOSET)) /* copy the boot ROM to memory and configure */
return SCPE_IERR; /* return an internal error if the copy failed */
cpu_ibl (dr_rom, dev, IBL_S_NOCLR, IBL_S_NOSET); /* copy the boot ROM to memory and configure */
WritePW (PR + BBDL_MAX_ADDR, ReadPW (PR + IBL_END)); /* move the maximum address word */
WritePW (PR + BBDL_DMA_CNTL, dr_rom [BBDL_DMA_CNTL] + dev); /* set up the DMA control word */
mem_deposit (PR + BBDL_MAX_ADDR, mem_examine (PR + IBL_END)); /* move the maximum address word */
mem_deposit (PR + BBDL_DMA_CNTL, (HP_WORD) dr_rom [BBDL_DMA_CNTL] + dev); /* set up the DMA control word */
WritePW (PR + IBL_DPC, dr_rom [IBL_DPC]); /* restore the overwritten word */
WritePW (PR + IBL_END, dr_rom [IBL_END]); /* restore the overwritten word */
mem_deposit (PR + IBL_DPC, (HP_WORD) dr_rom [IBL_DPC]); /* restore the overwritten word */
mem_deposit (PR + IBL_END, (HP_WORD) dr_rom [IBL_END]); /* restore the overwritten word */
PR = PR + BBDL_DISC_START; /* select the starting address */

View File

@@ -1,7 +1,7 @@
/* hp2100_ds.c: HP 13037D/13175D disc controller/interface simulator
Copyright (c) 2004-2012, Robert M. Supnik
Copyright (c) 2012-2016 J. David Bryan
Copyright (c) 2012-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 +26,11 @@
DS 13037D/13175D disc controller/interface
11-Jul-17 JDB Renamed "ibl_copy" to "cpu_ibl"
15-Mar-17 JDB Trace flags are now global
Changed DEBUG_PRI calls to tprintfs
10-Mar-17 JDB Added IOBUS to the debug table
09-Mar-17 JDB Deprecated LOCKED/WRITEENABLED for PROTECT/UNPROTECT
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
@@ -122,6 +127,7 @@
#include "hp2100_defs.h"
#include "hp2100_cpu.h"
#include "hp2100_disclib.h"
@@ -142,16 +148,6 @@
#define PRESET_ENABLE TRUE /* Preset Jumper (W4) is enabled */
/* Debug flags */
#define DEB_CPU (1 << 0) /* words received from and sent to the CPU */
#define DEB_CMDS (1 << 1) /* interface commands received from the CPU */
#define DEB_BUF (1 << 2) /* data read from and written to the card FIFO */
#define DEB_RWSC (1 << 3) /* device read/write/status/control commands */
#define DEB_SERV (1 << 4) /* unit service scheduling calls */
/* Per-card state variables */
typedef struct {
@@ -305,17 +301,23 @@ static REG ds_reg [] = {
};
static MTAB ds_mod [] = {
/* mask match pstring mstring valid disp desc */
{ UNIT_UNLOAD, UNIT_UNLOAD, "heads unloaded", "UNLOADED", &ds_load_unload, NULL, NULL },
{ UNIT_UNLOAD, 0, "heads loaded", "LOADED", &ds_load_unload, NULL, NULL },
/* Mask Value Match Value Print String Match String Validation Display Descriptor */
/* ------------ ------------ ----------------- --------------- ---------------- ------- ---------- */
{ UNIT_UNLOAD, UNIT_UNLOAD, "heads unloaded", "UNLOADED", &ds_load_unload, NULL, NULL },
{ UNIT_UNLOAD, 0, "heads loaded", "LOADED", &ds_load_unload, NULL, NULL },
{ UNIT_WLK, UNIT_WLK, "write locked", "LOCKED", NULL, NULL, NULL },
{ UNIT_WLK, 0, "write enabled", "WRITEENABLED", NULL, NULL, NULL },
{ UNIT_WLK, UNIT_WLK, "protected", "PROTECT", NULL, NULL, NULL },
{ UNIT_WLK, 0, "unprotected", "UNPROTECT", NULL, NULL, NULL },
{ UNIT_FMT, UNIT_FMT, "format enabled", "FORMAT", NULL, NULL, NULL },
{ UNIT_FMT, 0, "format disabled", "NOFORMAT", NULL, NULL, NULL },
{ UNIT_WLK, UNIT_WLK, NULL, "LOCKED", NULL, NULL, NULL },
{ UNIT_WLK, 0, NULL, "WRITEENABLED", NULL, NULL, NULL },
/* mask match pstring mstring valid disp desc */
{ UNIT_FMT, UNIT_FMT, "format enabled", "FORMAT", NULL, NULL, NULL },
{ UNIT_FMT, 0, "format disabled", "NOFORMAT", NULL, NULL, NULL },
/* Print Match */
/* Mask Value Match Value String String Validation Disp Desc */
/* --------------------------------- --------------------- ---------- ---------- ------------- ---- ---- */
{ UNIT_AUTO | UNIT_ATT, UNIT_AUTO, "autosize", "AUTOSIZE", &dl_set_model, NULL, NULL },
{ UNIT_AUTO | UNIT_ATT | UNIT_MODEL, MODEL_7905, "7905", "7905", &dl_set_model, NULL, NULL },
{ UNIT_AUTO | UNIT_ATT | UNIT_MODEL, MODEL_7906, "7906", "7906", &dl_set_model, NULL, NULL },
@@ -326,18 +328,21 @@ static MTAB ds_mod [] = {
{ UNIT_ATT | UNIT_MODEL, UNIT_ATT | MODEL_7920, "7920", NULL, NULL, NULL, NULL },
{ UNIT_ATT | UNIT_MODEL, UNIT_ATT | MODEL_7925, "7925", NULL, NULL, NULL, NULL },
{ MTAB_XTD | MTAB_VDV, 0, "SC", "SC", &hp_setsc, &hp_showsc, &ds_dev },
{ MTAB_XTD | MTAB_VDV | MTAB_NMO, 0, "DEVNO", "DEVNO", &hp_setdev, &hp_showdev, &ds_dev },
/* Entry Flags Value Print String Match String Validation Display Descriptor */
/* ------------------- ----- ------------ ------------ ------------ ------------- ---------------- */
{ MTAB_XDV, 1u, "SC", "SC", &hp_set_dib, &hp_show_dib, (void *) &ds_dib },
{ MTAB_XDV | MTAB_NMO, ~1u, "DEVNO", "DEVNO", &hp_set_dib, &hp_show_dib, (void *) &ds_dib },
{ 0 }
};
static DEBTAB ds_deb [] = {
{ "CPU", DEB_CPU },
{ "CMDS", DEB_CMDS },
{ "BUF", DEB_BUF },
{ "RWSC", DEB_RWSC },
{ "SERV", DEB_SERV },
{ NULL, 0 }
{ "RWSC", DEB_RWSC },
{ "CMDS", DEB_CMDS },
{ "CPU", DEB_CPU },
{ "BUF", DEB_BUF },
{ "SERV", DEB_SERV },
{ "IOBUS", TRACE_IOBUS },
{ NULL, 0 }
};
DEVICE ds_dev = {
@@ -446,8 +451,7 @@ while (working_set) {
ds.flag = CLEAR; /* clear the flag */
ds.flagbuf = CLEAR; /* and flag buffer */
if (DEBUG_PRI (ds_dev, DEB_CMDS))
fputs (">>DS cmds: [CLF] Flag cleared\n", sim_deb);
tprintf (ds_dev, DEB_CMDS, "[CLF] Flag cleared\n");
break;
@@ -456,8 +460,7 @@ while (working_set) {
ds.flag = SET; /* set the flag */
ds.flagbuf = SET; /* and flag buffer */
if (DEBUG_PRI (ds_dev, DEB_CMDS))
fputs (">>DS cmds: [STF] Flag set\n", sim_deb);
tprintf (ds_dev, DEB_CMDS, "[STF] Flag set\n");
break;
@@ -475,12 +478,11 @@ while (working_set) {
data = fifo_unload (); /* unload the next word from the FIFO */
stat_data = IORETURN (SCPE_OK, data); /* merge in the return status */
if (DEBUG_PRI (ds_dev, DEB_CPU))
fprintf (sim_deb, ">>DS cpu: [LIx%s] Data = %06o\n", hold_or_clear, data);
tprintf (ds_dev, DEB_CPU, "[LIx%s] Data = %06o\n", hold_or_clear, data);
if (FIFO_EMPTY) { /* is the FIFO now empty? */
if (ds.srq == SET && DEBUG_PRI (ds_dev, DEB_CMDS))
fprintf (sim_deb, ">>DS cmds: [LIx%s] SRQ cleared\n", hold_or_clear);
if (ds.srq == SET)
tprintf (ds_dev, DEB_CMDS, "[LIx%s] SRQ cleared\n", hold_or_clear);
ds.srq = CLEAR; /* clear SRQ */
@@ -495,9 +497,8 @@ while (working_set) {
case ioIOO: /* I/O data output */
data = IODATA (stat_data); /* mask to just the data word */
if (DEBUG_PRI (ds_dev, DEB_CPU))
fprintf (sim_deb, ">>DS cpu: [OTx%s] %s = %06o\n",
hold_or_clear, output_state [ds.cmfol], data);
tprintf (ds_dev, DEB_CPU, "[OTx%s] %s = %06o\n",
hold_or_clear, output_state [ds.cmfol], data);
fifo_load (data); /* load the word into the FIFO */
@@ -514,8 +515,8 @@ while (working_set) {
}
if (FIFO_STOP) { /* is the FIFO now full enough? */
if (ds.srq == SET && DEBUG_PRI (ds_dev, DEB_CMDS))
fprintf (sim_deb, ">>DS cmds: [OTx%s] SRQ cleared\n", hold_or_clear);
if (ds.srq == SET)
tprintf (ds_dev, DEB_CMDS, "[OTx%s] SRQ cleared\n", hold_or_clear);
ds.srq = CLEAR; /* clear SRQ to stop filling */
}
@@ -528,14 +529,12 @@ while (working_set) {
ds.flagbuf = SET; /* and flag buffer */
ds.cmrdy = CLEAR; /* clear the command ready flip-flop */
if (DEBUG_PRI (ds_dev, DEB_CMDS))
fputs (">>DS cmds: [POPIO] Flag set\n", sim_deb);
tprintf (ds_dev, DEB_CMDS, "[POPIO] Flag set\n");
break;
case ioCRS: /* control reset */
if (DEBUG_PRI (ds_dev, DEB_CMDS))
fputs (">>DS cmds: [CRS] Master reset\n", sim_deb);
tprintf (ds_dev, DEB_CMDS, "[CRS] Master reset\n");
ds.control = CLEAR; /* clear the control */
ds.cmfol = CLEAR; /* and command follows flip-flops */
@@ -552,8 +551,7 @@ while (working_set) {
case ioCLC: /* clear control flip-flop */
if (DEBUG_PRI (ds_dev, DEB_CMDS))
fprintf (sim_deb, ">>DS cmds: [CLC%s] Control cleared\n", hold_or_clear);
tprintf (ds_dev, DEB_CMDS, "[CLC%s] Control cleared\n", hold_or_clear);
ds.control = CLEAR; /* clear the control */
ds.edt = CLEAR; /* and EDT flip-flops */
@@ -569,16 +567,14 @@ while (working_set) {
interrupt_enabled = TRUE; /* check for drive attention */
if (DEBUG_PRI (ds_dev, DEB_CMDS))
fprintf (sim_deb, ">>DS cmds: [STC%s] Control set\n", hold_or_clear);
tprintf (ds_dev, DEB_CMDS, "[STC%s] Control set\n", hold_or_clear);
break;
case ioEDT: /* end data transfer */
ds.edt = SET; /* set the EDT flip-flop */
if (DEBUG_PRI (ds_dev, DEB_CPU))
fputs (">>DS cpu: [EDT] DCPC transfer ended\n", sim_deb);
tprintf (ds_dev, DEB_CPU, "[EDT] DCPC transfer ended\n");
break;
@@ -698,10 +694,8 @@ return stat_data;
t_stat ds_service_drive (UNIT *uptr)
{
static const char completion_message [] = ">>DS rwsc: Unit %d %s command completed\n";
t_stat result;
t_bool seek_completion;
int32 unit;
FLIP_FLOP entry_srq = ds.srq; /* get the SRQ state on entry */
CNTLR_PHASE entry_phase = (CNTLR_PHASE) uptr->PHASE; /* get the operation phase on entry */
uint32 entry_status = uptr->STAT; /* get the drive status on entry */
@@ -777,9 +771,8 @@ if ((CNTLR_PHASE) uptr->PHASE == data_phase) /* is the drive in the d
} /* end of data phase operation dispatch */
if (DEBUG_PRI (ds_dev, DEB_CMDS) && entry_srq != ds.srq)
fprintf (sim_deb, ">>DS cmds: SRQ %s\n", ds.srq == SET ? "set" : "cleared");
if (entry_srq != ds.srq)
tprintf (ds_dev, DEB_CMDS, "SRQ %s\n", ds.srq == SET ? "set" : "cleared");
if (uptr->wait) /* was service requested? */
activate_unit (uptr); /* schedule the next event */
@@ -795,22 +788,18 @@ if (mac_cntlr.state != cntlr_busy) { /* is the command co
}
if (DEBUG_PRI (ds_dev, DEB_RWSC)) {
unit = uptr - ds_unit; /* get the unit number */
if (result == SCPE_IERR) /* did an internal error occur? */
tprintf (ds_dev, DEB_RWSC, "Unit %d %s command %s phase service not handled\n",
uptr - ds_unit, dl_opcode_name (MAC, (CNTLR_OPCODE) uptr->OP),
dl_phase_name ((CNTLR_PHASE) uptr->PHASE));
if (result == SCPE_IERR) /* did an internal error occur? */
fprintf (sim_deb, ">>DS rwsc: Unit %d %s command %s phase service not handled\n",
unit, dl_opcode_name (MAC, (CNTLR_OPCODE) uptr->OP),
dl_phase_name ((CNTLR_PHASE) uptr->PHASE));
else if (seek_completion) /* if a seek has completed */
tprintf (ds_dev, DEB_RWSC, "Unit %d %s command completed\n", /* report the unit command */
uptr - ds_unit, dl_opcode_name (MAC, (CNTLR_OPCODE) uptr->OP));
else if (seek_completion) /* if a seek has completed */
fprintf (sim_deb, completion_message, /* report the unit command */
unit, dl_opcode_name (MAC, (CNTLR_OPCODE) uptr->OP));
else if (mac_cntlr.state == cntlr_wait) /* if the controller has stopped */
fprintf (sim_deb, completion_message, /* report the controller command */
unit, dl_opcode_name (MAC, mac_cntlr.opcode));
}
else if (mac_cntlr.state == cntlr_wait) /* if the controller has stopped */
tprintf (ds_dev, DEB_RWSC, "Unit %d %s command completed\n", /* report the controller command */
uptr - ds_unit, dl_opcode_name (MAC, mac_cntlr.opcode));
return result; /* return the result of the service */
}
@@ -932,8 +921,8 @@ switch ((CNTLR_PHASE) uptr->PHASE) { /* dispatch the current
} /* end of phase dispatch */
if (result == SCPE_IERR && DEBUG_PRI (ds_dev, DEB_RWSC)) /* did an internal error occur? */
fprintf (sim_deb, ">>DS rwsc: Controller %s command %s phase service not handled\n",
if (result == SCPE_IERR) /* did an internal error occur? */
tprintf (ds_dev, DEB_RWSC, "Controller %s command %s phase service not handled\n",
dl_opcode_name (MAC, opcode), dl_phase_name ((CNTLR_PHASE) uptr->PHASE));
@@ -941,9 +930,8 @@ if (mac_cntlr.state != cntlr_busy) { /* has the controller st
poll_interface (); /* poll the interface for the next command */
poll_drives (); /* poll the drives for Attention status */
if (DEBUG_PRI (ds_dev, DEB_RWSC))
fprintf (sim_deb, ">>DS rwsc: Controller %s command completed\n",
dl_opcode_name (MAC, opcode));
tprintf (ds_dev, DEB_RWSC, "Controller %s command completed\n",
dl_opcode_name (MAC, opcode));
}
return result; /* return the result of the service */
@@ -1172,12 +1160,11 @@ t_stat ds_boot (int32 unitno, DEVICE *dptr)
if (unitno != 0) /* boot supported on drive unit 0 only */
return SCPE_NOFNC; /* report "Command not allowed" if attempted */
if (ibl_copy (ds_rom, ds_dib.select_code, /* copy the boot ROM to memory and configure */
IBL_OPT | IBL_DS_HEAD, /* the S register accordingly */
IBL_DS | IBL_MAN | IBL_SET_SC (ds_dib.select_code)))
return SCPE_IERR; /* return an internal error if the copy failed */
else
return SCPE_OK;
cpu_ibl (ds_rom, ds_dib.select_code, /* copy the boot ROM to memory and configure */
IBL_OPT | IBL_DS_HEAD, /* the S register accordingly */
IBL_DS | IBL_MAN | IBL_SET_SC (ds_dib.select_code));
return SCPE_OK;
}
@@ -1273,23 +1260,16 @@ if (uptr) { /* did the command start
if (time) /* was the unit scheduled? */
activate_unit (uptr); /* activate it (and clear the "wait" field) */
if (DEBUG_PRI (ds_dev, DEB_RWSC)) {
unit = uptr - ds_unit; /* get the unit number */
if (time == 0) /* was the unit busy? */
tprintf (ds_dev, DEB_RWSC, "Unit %d %s in progress\n",
uptr - ds_unit, dl_opcode_name (MAC, drive_command));
if (time == 0) /* was the unit busy? */
fprintf (sim_deb, ">>DS rwsc: Unit %d %s in progress\n",
unit, dl_opcode_name (MAC, drive_command));
fputs (">>DS rwsc: ", sim_deb);
if (unit > DL_MAXDRIVE)
fputs ("Controller ", sim_deb);
else
fprintf (sim_deb, "Unit %d position %" T_ADDR_FMT "d ", unit, uptr->pos);
fprintf (sim_deb, "%s command initiated\n",
if (uptr - ds_unit > DL_MAXDRIVE)
tprintf (ds_dev, DEB_RWSC, "Controller %s command initiated\n",
dl_opcode_name (MAC, mac_cntlr.opcode));
}
else
tprintf (ds_dev, DEB_RWSC, "Unit %d position %" T_ADDR_FMT "d %s command initiated\n",
uptr - ds_unit, uptr->pos, dl_opcode_name (MAC, mac_cntlr.opcode));
}
else /* the command failed to start */
@@ -1380,8 +1360,7 @@ static void fifo_load (uint16 data)
uint32 index;
if (FIFO_FULL) { /* is the FIFO already full? */
if (DEBUG_PRI (ds_dev, DEB_BUF))
fprintf (sim_deb, ">>DS buf: Attempted load to full FIFO, data %06o\n", data);
tprintf (ds_dev, DEB_BUF, "Attempted load to full FIFO, data %06o\n", data);
return; /* return with the load ignored */
}
@@ -1391,9 +1370,8 @@ index = (ds.fifo_reg->qptr + ds.fifo_count) % FIFO_SIZE; /* calculate the ind
ds.fifo [index] = data; /* store the word in the FIFO */
ds.fifo_count = ds.fifo_count + 1; /* increment the count of words stored */
if (DEBUG_PRI (ds_dev, DEB_BUF))
fprintf (sim_deb, ">>DS buf: Data %06o loaded into FIFO (%d)\n",
data, ds.fifo_count);
tprintf (ds_dev, DEB_BUF, "Data %06o loaded into FIFO (%d)\n",
data, ds.fifo_count);
return;
}
@@ -1418,9 +1396,7 @@ static uint16 fifo_unload (void)
uint16 data;
if (FIFO_EMPTY) { /* is the FIFO already empty? */
if (DEBUG_PRI (ds_dev, DEB_BUF))
fputs (">>DS buf: Attempted unload from empty FIFO\n", sim_deb);
tprintf (ds_dev, DEB_BUF, "Attempted unload from empty FIFO\n");
return 0; /* return with no data */
}
@@ -1429,9 +1405,8 @@ data = ds.fifo [ds.fifo_reg->qptr]; /* get the word from
ds.fifo_reg->qptr = (ds.fifo_reg->qptr + 1) % FIFO_SIZE; /* update the FIFO queue pointer */
ds.fifo_count = ds.fifo_count - 1; /* decrement the count of words stored */
if (DEBUG_PRI (ds_dev, DEB_BUF))
fprintf (sim_deb, ">>DS buf: Data %06o unloaded from FIFO (%d)\n",
data, ds.fifo_count);
tprintf (ds_dev, DEB_BUF, "Data %06o unloaded from FIFO (%d)\n",
data, ds.fifo_count);
return data;
}
@@ -1446,8 +1421,7 @@ static void fifo_clear (void)
{
ds.fifo_count = 0; /* clear the FIFO */
if (DEBUG_PRI (ds_dev, DEB_BUF))
fputs (">>DS buf: FIFO cleared\n", sim_deb);
tprintf (ds_dev, DEB_BUF, "FIFO cleared\n");
return;
}
@@ -1461,19 +1435,14 @@ return;
static t_stat activate_unit (UNIT *uptr)
{
int32 unit;
t_stat result;
if (DEBUG_PRI (ds_dev, DEB_SERV)) {
unit = uptr - ds_unit; /* calculate the unit number */
if (uptr == &ds_cntlr)
fprintf (sim_deb, ">>DS serv: Controller delay %d service scheduled\n",
uptr->wait);
else
fprintf (sim_deb, ">>DS serv: Unit %d delay %d service scheduled\n",
unit, uptr->wait);
}
if (uptr == &ds_cntlr)
tprintf (ds_dev, DEB_SERV, "Controller delay %d service scheduled\n",
uptr->wait);
else
tprintf (ds_dev, DEB_SERV, "Unit %d delay %d service scheduled\n",
uptr - ds_unit, uptr->wait);
result = sim_activate (uptr, uptr->wait); /* activate the unit */
uptr->wait = 0; /* reset the activation time */

View File

@@ -1,28 +1,30 @@
/* hp2100_fp.c: HP 2100 floating point instructions
Copyright (c) 2002-2015, 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.
26-Jun-17 JDB Replaced SEXT with SEXT16
03-Jan-15 JDB Made the utility routines static
21-Jan-08 JDB Corrected fp_unpack mantissa high-word return
(from Mark Pizzolato)
@@ -228,13 +230,13 @@ UnpackFP (&fop1, FPAB); /* unpack A-B */
UnpackFP (&fop2, opnd); /* unpack op */
if (fop1.fr && fop2.fr) { /* if both != 0 */
res.exp = fop1.exp + fop2.exp + 1; /* exp = sum */
shi1 = SEXT (fop1.fr >> 16); /* mpy hi */
shi2 = SEXT (fop2.fr >> 16); /* mpc hi */
shi1 = SEXT16 (UPPER_WORD (fop1.fr)); /* mpy hi */
shi2 = SEXT16 (UPPER_WORD (fop2.fr)); /* mpc hi */
t1 = shi2 * ((int32) ((fop1.fr >> 1) & 077600)); /* mpc hi * (mpy lo/2) */
t2 = shi1 * ((int32) ((fop2.fr >> 1) & 077600)); /* mpc lo * (mpy hi/2) */
t3 = t1 + t2; /* cross product */
t4 = (shi1 * shi2) & ~1; /* mpy hi * mpc hi */
t5 = (SEXT (t3 >> 16)) << 1; /* add in cross */
t5 = SEXT16 (UPPER_WORD (t3)) << 1; /* add in cross */
res.fr = (t4 + t5) & DMASK32; /* bit<0> is lost */
}
return StoreFP (&res); /* store */
@@ -282,7 +284,7 @@ if (fop1.fr) { /* dvd != 0? */
q1 = divx (ba, dvrh, NULL); /* Q1 = rem / dvrh */
ba = (fop2.fr & 0xFF00) << 13; /* dvrl / 8 */
q2 = divx (ba, dvrh, NULL); /* dvrl / dvrh */
ba = -(SEXT (q2)) * (SEXT (q0)); /* -Q0 * Q2 */
ba = - SEXT16 (LOWER_WORD (q2)) * SEXT16 (LOWER_WORD (q0)); /* -Q0 * Q2 */
ba = (ba >> 16) & 0xFFFF; /* save ms half */
if (q1 & SIGN) quo.fr = quo.fr - 0x00010000; /* Q1 < 0? -1 */
if (ba & SIGN) quo.fr = quo.fr - 0x00010000; /* -Q0*Q2 < 0? */
@@ -372,8 +374,8 @@ uint32 val;
fop.fr = ((uint32) mantissa.fpk[0] << 16) | mantissa.fpk[1];
fop.exp = exponent;
val = PackFP (&fop);
result->fpk[0] = (int16) (val >> 16);
result->fpk[1] = (int16) val;
result->fpk[0] = UPPER_WORD (val);
result->fpk[1] = LOWER_WORD (val);
return 0;
}
@@ -401,8 +403,8 @@ uint32 operand;
operand = ((uint32) packed.fpk[0] << 16) | packed.fpk[1];
UnpackFP (&fop, operand);
mantissa->fpk[0] = (uint16) (fop.fr >> 16);
mantissa->fpk[1] = (uint16) fop.fr;
mantissa->fpk[0] = UPPER_WORD (fop.fr);
mantissa->fpk[1] = LOWER_WORD (fop.fr);
*exponent = fop.exp;
return 0;
}

View File

@@ -1,35 +1,35 @@
/* hp2100_fp.h: HP 2100/21MX floating point definitions
/* hp2100_fp.h: HP 2100/21MX floating point declarations
Copyright (c) 2002-2013, 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
AUTHORS 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.
15-Feb-17 JDB Deleted unneeded guard macro definition
14-Mar-13 MP Changed guard macro name to avoid reserved namespace
01-Dec-06 JDB Reworked FFP helpers for 1000-F support, deleted f_pwr2
26-Sep-06 JDB Moved from hp2100_fp.c to simplify extensions
*/
#ifndef HP2100_FP_H_
#define HP2100_FP_H_
/* Firmware floating-point routines */
@@ -44,5 +44,3 @@ uint32 f_flt (void); /* FLT */
uint32 fp_pack (OP *result, OP mantissa, int32 exponent, OPSIZE precision);
uint32 fp_nrpack (OP *result, OP mantissa, int32 exponent, OPSIZE precision);
uint32 fp_unpack (OP *mantissa, int32 *exponent, OP packed, OPSIZE precision);
#endif

View File

@@ -1,6 +1,6 @@
/* hp2100_fp1.h: HP 2100/1000 multiple-precision floating point definitions
/* hp2100_fp1.h: HP 2100/1000 multiple-precision floating point declarations
Copyright (c) 2005-2014, J. David Bryan
Copyright (c) 2005-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,14 +23,13 @@
in advertising or otherwise to promote the sale, use or other dealings in
this Software without prior written authorization from the author.
15-Feb-17 JDB Deleted unneeded guard macro definition
24-Dec-14 JDB Changed fp_ucom return from uint32 to uint16
14-Mar-13 MP Changed guard macro name to avoid reserved namespace
16-Oct-06 JDB Generalized FP calling sequences for F-Series
12-Oct-06 JDB Altered x_trun for F-Series FFP compatibility
*/
#ifndef HP2100_FP1_H_
#define HP2100_FP1_H_ 0
/* Special operands. */
@@ -51,5 +50,3 @@ uint16 fp_ucom (OP *mantissa, OPSIZE precision);
uint32 fp_pcom (OP *packed, OPSIZE precision);
uint32 fp_trun (OP *result, OP source, OPSIZE precision);
uint32 fp_cvt (OP *result, OPSIZE source_precision, OPSIZE dest_precision);
#endif

View File

@@ -1,30 +1,38 @@
/* hp2100_ipl.c: HP 2000 interprocessor link simulator
/* hp2100_ipl.c: HP 12875A Processor Interconnect simulator
Copyright (c) 2002-2016, Robert M Supnik
Copyright (c) 2002-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
AUTHORS 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.
IPLI, IPLO 12875A interprocessor link
IPLI, IPLO 12875A Processor Interconnect
13-Aug-17 JDB Revised so that only IPLI boots
19-Jul-17 JDB Removed unused "ipl_stopioe" variable and register
11-Jul-17 JDB Renamed "ibl_copy" to "cpu_ibl"
15-Mar-17 JDB Trace flags are now global
Changed DEBUG_PRJ calls to tpprintfs
10-Mar-17 JDB Added IOBUS to the debug table
27-Feb-17 JDB ibl_copy no longer returns a status code
05-Aug-16 JDB Renamed the P register from "PC" to "PR"
13-May-16 JDB Modified for revised SCP API function parameter types
14-Sep-15 JDB Exposed "ipl_edtdelay" via a REG_HIDDEN to allow user tuning
@@ -58,8 +66,8 @@
31-Jan-03 RMS Links are full duplex (found by Mike Gemeny)
Reference:
- 12875A Processor Interconnect Kit Operating and Service Manual
(12875-90002, Jan-1974)
- 12875A Processor Interconnect Kit Operating and Service Manual
(12875-90002, January 1974)
The 12875A Processor Interconnect Kit consists four 12566A Microcircuit
@@ -76,6 +84,7 @@
#include "hp2100_defs.h"
#include "hp2100_cpu.h"
#include "sim_sock.h"
#include "sim_tmxr.h"
#include "sim_rev.h"
@@ -103,17 +112,11 @@ typedef enum { ipli, iplo } CARD_INDEX; /* card index number */
#define DSOCKET u3 /* data socket */
#define LSOCKET u4 /* listening socket */
/* Debug flags */
#define DEB_CMDS (1 << 0) /* Command initiation and completion */
#define DEB_CPU (1 << 1) /* CPU I/O */
#define DEB_XFER (1 << 2) /* Socket receive and transmit */
extern DIB ptr_dib; /* need PTR select code for boot */
int32 ipl_edtdelay = 1; /* EDT delay (msec) */
int32 ipl_ptime = 31; /* polling interval */
int32 ipl_stopioe = 0; /* stop on error */
typedef struct {
FLIP_FLOP control; /* control flip-flop */
@@ -138,10 +141,11 @@ t_bool ipl_check_conn (UNIT *uptr);
/* Debug flags table */
DEBTAB ipl_deb [] = {
{ "CMDS", DEB_CMDS },
{ "CPU", DEB_CPU },
{ "XFER", DEB_XFER },
{ NULL, 0 }
{ "CMDS", DEB_CMDS },
{ "CPU", DEB_CPU },
{ "XFER", DEB_XFER },
{ "IOBUS", TRACE_IOBUS }, /* interface I/O bus signals and data words */
{ NULL, 0 }
};
/* Common structures */
@@ -184,7 +188,6 @@ REG ipli_reg [] = {
{ FLDATA (FBF, ipl [ipli].flagbuf, 0) },
{ ORDATA (HOLD, ipl [ipli].hold, 8) },
{ DRDATA (TIME, ipl_ptime, 24), PV_LEFT },
{ FLDATA (STOP_IOE, ipl_stopioe, 0) },
{ DRDATA (EDTDELAY, ipl_edtdelay, 32), REG_HIDDEN | PV_LEFT },
{ ORDATA (SC, ipli_dib.select_code, 6), REG_HRO },
{ ORDATA (DEVNO, ipli_dib.select_code, 6), REG_HRO },
@@ -192,22 +195,42 @@ REG ipli_reg [] = {
};
MTAB ipl_mod [] = {
{ UNIT_DIAG, UNIT_DIAG, "diagnostic mode", "DIAG", &ipl_setdiag },
{ UNIT_DIAG, 0, "link mode", "LINK", &ipl_setdiag },
{ MTAB_XTD | MTAB_VDV, 0, NULL, "DISCONNECT",
&ipl_dscln, NULL, NULL },
{ MTAB_XTD | MTAB_VDV, 1, "SC", "SC", &hp_setsc, &hp_showsc, &ipli_dev },
{ MTAB_XTD | MTAB_VDV | MTAB_NMO, 1, "DEVNO", "DEVNO", &hp_setdev, &hp_showdev, &ipli_dev },
/* Mask Value Match Value Print String Match String Validation Display Descriptor */
/* ---------- ----------- ----------------- ------------ ------------- ------- ---------- */
{ UNIT_DIAG, UNIT_DIAG, "diagnostic mode", "DIAGNOSTIC", &ipl_setdiag, NULL, NULL },
{ UNIT_DIAG, 0, "link mode", "LINK", &ipl_setdiag, NULL, NULL },
/* Entry Flags Value Print String Match String Validation Display Descriptor */
/* -------------------- ----- ------------ ------------ ------------ ------------- ----------------- */
{ MTAB_XDV, 0u, NULL, "DISCONNECT", &ipl_dscln, NULL, NULL },
{ MTAB_XDV, 2u, "SC", "SC", &hp_set_dib, &hp_show_dib, (void *) &ipl_dib },
{ MTAB_XDV | MTAB_NMO, ~2u, "DEVNO", "DEVNO", &hp_set_dib, &hp_show_dib, (void *) &ipl_dib },
{ 0 }
};
DEVICE ipli_dev = {
"IPLI", &ipli_unit, ipli_reg, ipl_mod,
1, 10, 31, 1, 16, 16,
&tmxr_ex, &tmxr_dep, &ipl_reset,
&ipl_boot, &ipl_attach, &ipl_detach,
&ipli_dib, DEV_DISABLE | DEV_DIS | DEV_DEBUG,
0, ipl_deb, NULL, NULL
"IPLI", /* device name */
&ipli_unit, /* unit array */
ipli_reg, /* register array */
ipl_mod, /* modifier array */
1, /* number of units */
10, /* address radix */
31, /* address width */
1, /* address increment */
16, /* data radix */
16, /* data width */
&tmxr_ex, /* examine routine */
&tmxr_dep, /* deposit routine */
&ipl_reset, /* reset routine */
&ipl_boot, /* boot routine */
&ipl_attach, /* attach routine */
&ipl_detach, /* detach routine */
&ipli_dib, /* device information block pointer */
DEV_DISABLE | DEV_DIS | DEV_DEBUG, /* device flags */
0, /* debug control flags */
ipl_deb, /* debug flag name table */
NULL, /* memory size change routine */
NULL /* logical device name */
};
/* IPLO data structures
@@ -231,12 +254,28 @@ REG iplo_reg [] = {
};
DEVICE iplo_dev = {
"IPLO", &iplo_unit, iplo_reg, ipl_mod,
1, 10, 31, 1, 16, 16,
&tmxr_ex, &tmxr_dep, &ipl_reset,
&ipl_boot, &ipl_attach, &ipl_detach,
&iplo_dib, DEV_DISABLE | DEV_DIS | DEV_DEBUG,
0, ipl_deb, NULL, NULL
"IPLO", /* device name */
&iplo_unit, /* unit array */
iplo_reg, /* register array */
ipl_mod, /* modifier array */
1, /* number of units */
10, /* address radix */
31, /* address width */
1, /* address increment */
16, /* data radix */
16, /* data width */
&tmxr_ex, /* examine routine */
&tmxr_dep, /* deposit routine */
&ipl_reset, /* reset routine */
NULL, /* boot routine */
&ipl_attach, /* attach routine */
&ipl_detach, /* detach routine */
&iplo_dib, /* device information block pointer */
DEV_DISABLE | DEV_DIS | DEV_DEBUG, /* device flags */
0, /* debug control flags */
ipl_deb, /* debug flag name table */
NULL, /* memory size change routine */
NULL /* logical device name */
};
@@ -326,9 +365,8 @@ IOSIGNAL signal;
IOCYCLE working_set = IOADDSIR (signal_set); /* add ioSIR if needed */
if (crs_count [card] && !(signal_set & ioCRS)) { /* counting CRSes and not present? */
if (DEBUG_PRJ (dptrs [card], DEB_CMDS)) /* report reset count */
fprintf (sim_deb, ">>%s cmds: [CRS] Control cleared %d times\n",
dptrs [card]->name, crs_count [card]);
tpprintf (dptrs [card], DEB_CMDS, "[CRS] Control cleared %d times\n",
crs_count [card]);
crs_count [card] = 0; /* clear counter */
}
@@ -362,16 +400,14 @@ while (working_set) {
case ioIOI: /* I/O data input */
stat_data = IORETURN (SCPE_OK, uptr->IBUF); /* get return data */
if (DEBUG_PRJ (dptrs [card], DEB_CPU))
fprintf (sim_deb, ">>%s cpu: [LIx] %s = %06o\n", dptrs [card]->name, iotype [card ^ 1], uptr->IBUF);
tpprintf (dptrs [card], DEB_CPU, "[LIx] %s = %06o\n", iotype [card ^ 1], uptr->IBUF);
break;
case ioIOO: /* I/O data output */
uptr->OBUF = IODATA (stat_data); /* clear supplied status */
if (DEBUG_PRJ (dptrs [card], DEB_CPU))
fprintf (sim_deb, ">>%s cpu: [OTx] %s = %06o\n", dptrs [card]->name, iotype [card], uptr->OBUF);
tpprintf (dptrs [card], DEB_CPU, "[OTx] %s = %06o\n", iotype [card], uptr->OBUF);
break;
@@ -392,36 +428,35 @@ while (working_set) {
case ioCLC: /* clear control flip-flop */
ipl [card].control = CLEAR; /* clear ctl */
if (DEBUG_PRJ (dptrs [card], DEB_CMDS))
fprintf (sim_deb, ">>%s cmds: [CLC] Control cleared\n", dptrs [card]->name);
tpprintf (dptrs [card], DEB_CMDS, "[CLC] Control cleared\n");
break;
case ioSTC: /* set control flip-flop */
if (DEBUG_PRJ (dptrs [card], DEB_CMDS))
fprintf (sim_deb, ">>%s cmds: [STC] Control set\n", dptrs [card]->name);
case ioSTC: /* set control flip-flop */
tpprintf (dptrs [card], DEB_CMDS, "[STC] Control set\n");
if (uptr->flags & UNIT_ATT) { /* attached? */
if (!ipl_check_conn (uptr)) /* not established? */
return IORETURN (STOP_NOCONN, 0); /* lose */
msg [0] = (uptr->OBUF >> 8) & 0377;
msg [1] = uptr->OBUF & 0377;
sta = sim_write_sock (uptr->DSOCKET, msg, 2);
if (DEBUG_PRJ (dptrs [card], DEB_XFER))
fprintf (sim_deb,
">>%s xfer: [STC] Socket write = %06o, status = %d\n",
dptrs [card]->name, uptr->OBUF, sta);
if (sta == SOCKET_ERROR) {
printf ("IPL socket write error\n");
return IORETURN (SCPE_IOERR, 0);
if (uptr->flags & UNIT_ATT) { /* attached? */
if (!ipl_check_conn (uptr)) { /* not established? */
cpu_ioerr_uptr = uptr; /* save the failing unit */
return IORETURN (STOP_NOCONN, 0); /* lose */
}
ipl [card].control = SET; /* set ctl */
msg [0] = UPPER_BYTE (uptr->OBUF);
msg [1] = LOWER_BYTE (uptr->OBUF);
sta = sim_write_sock (uptr->DSOCKET, msg, 2);
sim_os_sleep (0);
tpprintf (dptrs [card], DEB_XFER, "[STC] Socket write = %06o, status = %d\n",
uptr->OBUF, sta);
if (sta == SOCKET_ERROR) { /* if the write fails, report it to the console */
cprintf ("%s simulator processor interconnect socket write error\n",
sim_name);
return IORETURN (SCPE_IOERR, 0); /* and stop the simulator with an I/O error */
}
ipl [card].control = SET; /* set ctl */
sim_os_sleep (0); /* yield */
}
else if (uptr->flags & UNIT_DIAG) { /* diagnostic mode? */
@@ -440,10 +475,8 @@ while (working_set) {
(signal_set & ioIOO) && /* and doing output? */
(card == ipli)) { /* on the input card? */
if (DEBUG_PRJ (dptrs [card], DEB_CMDS))
fprintf (sim_deb,
">>%s cmds: [EDT] Delaying DMA completion interrupt for %d msec\n",
dptrs [card]->name, ipl_edtdelay);
tpprintf (dptrs [card], DEB_CMDS, "[EDT] Delaying DMA completion interrupt for %d msec\n",
ipl_edtdelay);
sim_os_ms_sleep (ipl_edtdelay); /* delay completion */
}
@@ -492,7 +525,8 @@ if (!ipl_check_conn (uptr)) /* check for conn */
nb = sim_read_sock (uptr->DSOCKET, msg, ((uptr->flags & UNIT_HOLD)? 1: 2));
if (nb < 0) { /* connection closed? */
printf ("IPL socket read error\n");
cprintf ("%s simulator processor interconnect socket read error\n",
sim_name);
return SCPE_IOERR;
}
@@ -514,9 +548,8 @@ else
iplio ((DIB *) dptrs [card]->ctxt, ioENF, 0); /* set flag */
if (DEBUG_PRJ (dptrs [card], DEB_XFER))
fprintf (sim_deb, ">>%s xfer: Socket read = %06o, status = %d\n",
dptrs [card]->name, uptr->IBUF, nb);
tpprintf (dptrs [card], DEB_XFER, "Socket read = %06o, status = %d\n",
uptr->IBUF, nb);
return SCPE_OK;
}
@@ -622,10 +655,7 @@ if ((sim_switches & SWMASK ('C')) || /* connecting? */
if (newsock == INVALID_SOCKET)
return SCPE_IOERR;
printf ("Connecting to %s\n", hostport);
if (sim_log)
fprintf (sim_log, "Connecting to %s\n", hostport);
cprintf ("Connecting to %s\n", hostport);
uptr->flags = uptr->flags | UNIT_ACTV;
uptr->LSOCKET = 0;
@@ -641,9 +671,7 @@ else {
return r;
if (newsock == INVALID_SOCKET)
return SCPE_IOERR;
printf ("Listening on port %s\n", hostport);
if (sim_log)
fprintf (sim_log, "Listening on port %s\n", hostport);
cprintf ("Listening on port %s\n", hostport);
uptr->flags = uptr->flags & ~UNIT_ACTV;
uptr->LSOCKET = newsock;
uptr->DSOCKET = 0;
@@ -674,14 +702,9 @@ if ((sim_switches & SWMASK ('C')) ||
newsock = sim_connect_sock (ipa, ipp);
if (newsock == INVALID_SOCKET)
return SCPE_IOERR;
printf ("Connecting to IP address %d.%d.%d.%d, port %d\n",
(ipa >> 24) & 0xff, (ipa >> 16) & 0xff,
(ipa >> 8) & 0xff, ipa & 0xff, ipp);
if (sim_log)
fprintf (sim_log,
"Connecting to IP address %d.%d.%d.%d, port %d\n",
(ipa >> 24) & 0xff, (ipa >> 16) & 0xff,
(ipa >> 8) & 0xff, ipa & 0xff, ipp);
cprintf ("Connecting to IP address %d.%d.%d.%d, port %d\n",
(ipa >> 24) & 0xff, (ipa >> 16) & 0xff,
(ipa >> 8) & 0xff, ipa & 0xff, ipp);
uptr->flags = uptr->flags | UNIT_ACTV;
uptr->LSOCKET = 0;
uptr->DSOCKET = newsock;
@@ -692,9 +715,7 @@ else {
newsock = sim_master_sock (ipp);
if (newsock == INVALID_SOCKET)
return SCPE_IOERR;
printf ("Listening on port %d\n", ipp);
if (sim_log)
fprintf (sim_log, "Listening on port %d\n", ipp);
cprintf ("Listening on port %d\n", ipp);
uptr->flags = uptr->flags & ~UNIT_ACTV;
uptr->LSOCKET = newsock;
uptr->DSOCKET = 0;
@@ -718,11 +739,11 @@ if (sim_switches & SWMASK ('W')) { /* wait? */
if (t) /* established? */
break;
if ((i % 10) == 0) /* status every 10 sec */
printf ("Waiting for connection\n");
cprintf ("Waiting for connection\n");
sim_os_sleep (1); /* sleep 1 sec */
}
if (t) /* if connected (set by "ipl_check_conn" above) */
printf ("Connection established\n"); /* then report */
cprintf ("Connection established\n"); /* then report */
}
return SCPE_OK;
}
@@ -860,17 +881,16 @@ static const BOOT_ROM ipl_rom = {
t_stat ipl_boot (int32 unitno, DEVICE *dptr)
{
const int32 devi = ipli_dib.select_code;
const int32 devp = ptr_dib.select_code;
const HP_WORD devi = (HP_WORD) ipli_dib.select_code;
const HP_WORD devp = (HP_WORD) ptr_dib.select_code;
if (ibl_copy (ipl_rom, devi, IBL_S_CLR, /* copy the boot ROM to memory and configure */
IBL_SET_SC (devi) | devp)) /* the S register accordingly */
return SCPE_IERR; /* return an internal error if the copy failed */
cpu_ibl (ipl_rom, devi, IBL_S_CLR, /* copy the boot ROM to memory and configure */
IBL_SET_SC (devi) | devp); /* the S register accordingly */
WritePW (PR + MAX_BASE, (~PR + 1) & DMASK); /* fix ups */
WritePW (PR + IPL_PNTR, ipl_rom [IPL_PNTR] | PR);
WritePW (PR + PTR_PNTR, ipl_rom [PTR_PNTR] | PR);
WritePW (PR + IPL_DEVA, devi);
WritePW (PR + PTR_DEVA, devp);
mem_deposit (PR + MAX_BASE, (~PR + 1) & DMASK); /* fix ups */
mem_deposit (PR + IPL_PNTR, (HP_WORD) ipl_rom [IPL_PNTR] | PR);
mem_deposit (PR + PTR_PNTR, (HP_WORD) ipl_rom [PTR_PNTR] | PR);
mem_deposit (PR + IPL_DEVA, devi);
mem_deposit (PR + PTR_DEVA, devp);
return SCPE_OK;
}

View File

@@ -1,31 +1,35 @@
/* hp2100_lps.c: HP 2100 12653A/2767 line printer simulator
/* hp2100_lps.c: HP 2100 12653A Line Printer Interface 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"),
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
AUTHORS 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.
LPS 12653A 2767 line printer
12566B microcircuit interface with loopback diagnostic connector
LPS HP 12653A Line Printer Interface
03-Aug-17 JDB Changed perror call for I/O errors to cprintf
20-Jul-17 JDB Removed "lps_stopioe" variable and register
17-Mar-17 JDB Added "-N" handling to the attach routine
15-Mar-17 JDB Changed DEBUG_PRS calls to tprintfs
13-May-16 JDB Modified for revised SCP API function parameter types
10-Feb-12 JDB Deprecated DEVNO in favor of SC
28-Mar-11 JDB Tidied up signal handling
@@ -58,30 +62,17 @@
15-Oct-00 RMS Added variable device number support
References:
- 2767A Line Printer Operating and Service Manual (02767-90002, Oct-1973)
- 12566B, 12566B-001, 12566B-002, 12566B-003 Microcircuit Interface Kits
Operating and Service Manual (12566-90015, Apr-1976)
This module simulates two different devices. In "diagnostic mode," it
simulates a 12566B microcircuit interface card with a loopback connector. In
non-diagnostic mode, it simulates a 12653A line printer interface card and a
2767 line printer.
In diagnostic mode, the 12566B interface has a loopback connector that ties
the output data lines to the input data lines and the device command output
to the device flag input. In addition, card configuration jumpers are set as
needed for the diagnostic programs.
Jumper settings depend on the CPU model. For the 2114/15/16 CPUs, jumper W1
is installed in position B and jumper W2 in position C. In these positions,
the card flag sets two instructions after the STC, allowing DMA to steal
every third cycle. For the 2100 and 1000 CPUs, jumper W1 is installed in
position C and jumper W2 in position B. In these positions, the card flag
sets one instruction after the STC, allowing DMA to steal every other cycle.
For all CPUs, jumpers W3 and W4 are installed in position B, W5-W8 are
installed, and W9 is installed in position A.
- 2767A Line Printer Operating and Service Manual
(02767-90002, October 1973)
- General Purpose Register Diagnostic Reference Manual
(24391-90001, April 1982)
The HP 12653A Line Printer Interface Kit connects the 2767A printer to the HP
1000 family. The subsystem consists of an interface card employing TTL-level
line drivers and receivers, an interconnecting cable, and an HP 2767A (from
356 to 1110 lines per minute) line printer. The interface is supported by
RTE and DOS drivers DVR12. The interface supports DMA transfers, but the OS
drivers do not use them.
The 2767 impact printer has a rotating drum with 80 columns of 64 raised
characters. ASCII codes 32 through 95 (SPACE through "_") form the print
@@ -131,45 +122,75 @@
2. Print operation in progress sets BUSY instead of NOT READY.
3. Characters not in the print repertoire are replaced with blanks.
4. The 81st and succeeding characters overprint the current line.
*/
The "General Purpose Register Diagnostic Reference Manual" states that the
12653A is a "special microcircuit interface," suggesting that it is a
derivative of the 12566B Microcircuit Interface Kit. No specific manual for
this interface kit has been found.
A diagnostic mode is provided to simulate the installation of the 1251-0332
loopback connecctor, modified to connect pins Z/22 to pins AA/23 as required
by the diagnostic. This ties the output data lines to the input data lines
and the device command output to the device flag input.
Jumper settings depend on the CPU model. For the 2114/15/16 CPUs, jumper W1
is installed in position B and jumper W2 in position C. In these positions,
the card flag sets two instructions after the STC, allowing DMA to steal
every third cycle. For the 2100 and 1000 CPUs, jumper W1 is installed in
position C and jumper W2 in position B. In these positions, the card flag
sets one instruction after the STC, allowing DMA to steal every other cycle.
For all CPUs, jumpers W3 and W4 are installed in position B, W5-W8 are
installed, and W9 is installed in position A.
*/
#include "hp2100_defs.h"
#include "hp2100_cpu.h"
#define LPS_ZONECNT 20 /* zone char count */
#define LPS_PAGECNT 80 /* page char count */
#define LPS_PAGELNT 60 /* page line length */
#define LPS_FORMLNT 66 /* form line length */
/* Printer program constants */
#define CR '\r' /* carriage return */
#define LF '\n' /* line feed */
#define FF '\f' /* form feed */
#define DATA_MASK 0177u /* printer uses only 7 bits for data */
#define LPS_ZONECNT 20 /* zone char count */
#define LPS_PAGECNT 80 /* page char count */
#define LPS_PAGELNT 60 /* page line length */
#define LPS_FORMLNT 66 /* form line length */
/* Printer power states */
#define LPS_ON 0 /* power is on */
#define LPS_OFF 1 /* power is off */
#define LPS_TURNING_ON 2 /* power is turning on */
#define LPS_ON 0 /* power is on */
#define LPS_OFF 1 /* power is off */
#define LPS_TURNING_ON 2 /* power is turning on */
#define LPS_BUSY 0000001 /* busy status */
#define LPS_NRDY 0100000 /* not ready status */
#define LPS_PWROFF LPS_BUSY | LPS_NRDY /* power-off status */
#define LPS_BUSY 0000001 /* busy status */
#define LPS_NRDY 0100000 /* not ready status */
#define LPS_PWROFF LPS_BUSY | LPS_NRDY /* power-off status */
#define UNIT_V_DIAG (UNIT_V_UF + 0) /* diagnostic mode */
#define UNIT_V_POWEROFF (UNIT_V_UF + 1) /* unit powered off */
#define UNIT_V_OFFLINE (UNIT_V_UF + 2) /* unit offline */
#define UNIT_V_DIAG (UNIT_V_UF + 0) /* diagnostic mode */
#define UNIT_V_POWEROFF (UNIT_V_UF + 1) /* unit powered off */
#define UNIT_V_OFFLINE (UNIT_V_UF + 2) /* unit offline */
#define UNIT_DIAG (1 << UNIT_V_DIAG)
#define UNIT_POWEROFF (1 << UNIT_V_POWEROFF)
#define UNIT_OFFLINE (1 << UNIT_V_OFFLINE)
struct {
FLIP_FLOP control; /* control flip-flop */
FLIP_FLOP flag; /* flag flip-flop */
FLIP_FLOP flagbuf; /* flag buffer flip-flop */
static struct {
FLIP_FLOP control; /* control flip-flop */
FLIP_FLOP flag; /* flag flip-flop */
FLIP_FLOP flagbuf; /* flag buffer flip-flop */
} lps = { CLEAR, CLEAR, CLEAR };
int32 lps_ccnt = 0; /* character count */
int32 lps_lcnt = 0; /* line count */
int32 lps_stopioe = 0; /* stop on error */
int32 lps_sta = 0; /* printer status */
int32 lps_timing = 1; /* timing type */
uint32 lps_power = LPS_ON; /* power state */
static int32 lps_ccnt = 0; /* character count */
static int32 lps_lcnt = 0; /* line count */
static int32 lps_sta = 0; /* printer status */
static int32 lps_timing = 1; /* timing type */
static uint32 lps_power = LPS_ON; /* power state */
/* Hardware timing:
(based on 1580 instr/msec) instr msec calc msec
@@ -191,32 +212,32 @@ uint32 lps_power = LPS_ON; /* power state */
three-fourths when not executing on an E/F.
*/
int32 lps_ctime = 0; /* char xfer time */
int32 lps_ptime = 0; /* zone printing time */
int32 lps_stime = 0; /* paper slew time */
int32 lps_rtime = 0; /* power-on ready time */
static int32 lps_ctime = 0; /* char xfer time */
static int32 lps_ptime = 0; /* zone printing time */
static int32 lps_stime = 0; /* paper slew time */
static int32 lps_rtime = 0; /* power-on ready time */
typedef int32 TIMESET[4]; /* set of controller times */
typedef int32 TIMESET[4]; /* set of controller times */
int32 *const lps_timers[] = { &lps_ctime, &lps_ptime, &lps_stime, &lps_rtime };
static int32 *const lps_timers[] = { &lps_ctime, &lps_ptime, &lps_stime, &lps_rtime };
const TIMESET lps_times[2] = {
{ 2, 55300, 17380, 158000 }, /* REALTIME */
{ 2, 1000, 1000, 1000 } /* FASTTIME */
static const TIMESET lps_times[2] = {
{ 2, 55300, 17380, 158000 }, /* REALTIME */
{ 2, 1000, 1000, 1000 } /* FASTTIME */
};
DEVICE lps_dev;
IOHANDLER lpsio;
static IOHANDLER lpsio;
t_stat lps_svc (UNIT *uptr);
t_stat lps_reset (DEVICE *dptr);
t_stat lps_restart (UNIT *uptr, int32 value, CONST char *cptr, void *desc);
t_stat lps_poweroff (UNIT *uptr, int32 value, CONST char *cptr, void *desc);
t_stat lps_poweron (UNIT *uptr, int32 value, CONST char *cptr, void *desc);
t_stat lps_attach (UNIT *uptr, CONST char *cptr);
t_stat lps_set_timing (UNIT *uptr, int32 val, CONST char *cptr, void *desc);
t_stat lps_show_timing (FILE *st, UNIT *uptr, int32 val, CONST void *desc);
static t_stat lps_svc (UNIT *uptr);
static t_stat lps_reset (DEVICE *dptr);
static t_stat lps_restart (UNIT *uptr, int32 value, CONST char *cptr, void *desc);
static t_stat lps_poweroff (UNIT *uptr, int32 value, CONST char *cptr, void *desc);
static t_stat lps_poweron (UNIT *uptr, int32 value, CONST char *cptr, void *desc);
static t_stat lps_attach (UNIT *uptr, CONST char *cptr);
static t_stat lps_set_timing (UNIT *uptr, int32 val, CONST char *cptr, void *desc);
static t_stat lps_show_timing (FILE *st, UNIT *uptr, int32 val, CONST void *desc);
/* LPS data structures
@@ -225,57 +246,89 @@ t_stat lps_show_timing (FILE *st, UNIT *uptr, int32 val, CONST void *desc);
lps_reg LPS register list
*/
DIB lps_dib = { &lpsio, LPS };
static DIB lps_dib = { &lpsio, LPS };
UNIT lps_unit = {
static UNIT lps_unit = {
UDATA (&lps_svc, UNIT_SEQ+UNIT_ATTABLE+UNIT_DISABLE+UNIT_TEXT, 0)
};
REG lps_reg[] = {
{ ORDATA (BUF, lps_unit.buf, 16) },
{ ORDATA (STA, lps_sta, 16) },
{ ORDATA (POWER, lps_power, 2), REG_RO },
{ FLDATA (CTL, lps.control, 0) },
{ FLDATA (FLG, lps.flag, 0) },
{ FLDATA (FBF, lps.flagbuf, 0) },
{ DRDATA (CCNT, lps_ccnt, 7), PV_LEFT },
{ DRDATA (LCNT, lps_lcnt, 7), PV_LEFT },
{ DRDATA (POS, lps_unit.pos, T_ADDR_W), PV_LEFT },
{ DRDATA (CTIME, lps_ctime, 24), PV_LEFT },
{ DRDATA (PTIME, lps_ptime, 24), PV_LEFT },
{ DRDATA (STIME, lps_stime, 24), PV_LEFT },
{ DRDATA (RTIME, lps_rtime, 24), PV_LEFT },
{ FLDATA (TIMING, lps_timing, 0), REG_HRO },
{ FLDATA (STOP_IOE, lps_stopioe, 0) },
{ ORDATA (SC, lps_dib.select_code, 6), REG_HRO },
{ ORDATA (DEVNO, lps_dib.select_code, 6), REG_HRO },
static REG lps_reg[] = {
/* Macro Name Location Width Offset Flags */
/* ------ ------ ------------------- --------- ------ ------- */
{ ORDATA (BUF, lps_unit.buf, 16), REG_X },
{ ORDATA (STA, lps_sta, 16) },
{ ORDATA (POWER, lps_power, 2), REG_RO },
{ FLDATA (CTL, lps.control, 0) },
{ FLDATA (FLG, lps.flag, 0) },
{ FLDATA (FBF, lps.flagbuf, 0) },
{ DRDATA (CCNT, lps_ccnt, 7), PV_LEFT },
{ DRDATA (LCNT, lps_lcnt, 7), PV_LEFT },
{ DRDATA (POS, lps_unit.pos, T_ADDR_W), PV_LEFT },
{ DRDATA (CTIME, lps_ctime, 24), PV_LEFT },
{ DRDATA (PTIME, lps_ptime, 24), PV_LEFT },
{ DRDATA (STIME, lps_stime, 24), PV_LEFT },
{ DRDATA (RTIME, lps_rtime, 24), PV_LEFT },
{ FLDATA (TIMING, lps_timing, 0), REG_HRO },
{ ORDATA (SC, lps_dib.select_code, 6), REG_HRO },
{ ORDATA (DEVNO, lps_dib.select_code, 6), REG_HRO },
{ NULL }
};
MTAB lps_mod[] = {
{ UNIT_DIAG, UNIT_DIAG, "diagnostic mode", "DIAG", NULL },
{ UNIT_DIAG, 0, "printer mode", "PRINTER", NULL },
{ UNIT_POWEROFF, UNIT_POWEROFF, "power off", "POWEROFF", lps_poweroff },
{ UNIT_POWEROFF, 0, "power on", "POWERON", lps_poweron },
{ UNIT_OFFLINE, UNIT_OFFLINE, "offline", "OFFLINE", NULL },
{ UNIT_OFFLINE, 0, "online", "ONLINE", lps_restart },
{ MTAB_XTD | MTAB_VDV, 0, NULL, "REALTIME",
&lps_set_timing, NULL, NULL },
{ MTAB_XTD | MTAB_VDV, 1, NULL, "FASTTIME",
&lps_set_timing, NULL, NULL },
{ MTAB_XTD | MTAB_VDV, 0, "TIMING", NULL,
NULL, &lps_show_timing, NULL },
{ MTAB_XTD | MTAB_VDV, 0, "SC", "SC", &hp_setsc, &hp_showsc, &lps_dev },
{ MTAB_XTD | MTAB_VDV | MTAB_NMO, 0, "DEVNO", "DEVNO", &hp_setdev, &hp_showdev, &lps_dev },
static MTAB lps_mod[] = {
/* Mask Value Match Value Print String Match String Validation Display Descriptor */
/* ------------- ------------- ----------------- ------------- ------------------ ------- ---------- */
{ UNIT_DIAG, UNIT_DIAG, "diagnostic mode", "DIAGNOSTIC", NULL, NULL, NULL },
{ UNIT_DIAG, 0, "printer mode", "PRINTER", NULL, NULL, NULL },
{ UNIT_OFFLINE, UNIT_OFFLINE, "offline", "OFFLINE", NULL, NULL, NULL },
{ UNIT_OFFLINE, 0, "online", "ONLINE", &lps_restart, NULL, NULL },
{ UNIT_POWEROFF, UNIT_POWEROFF, "power off", "POWEROFF", &lps_poweroff, NULL, NULL },
{ UNIT_POWEROFF, 0, "power on", "POWERON", &lps_poweron, NULL, NULL },
/* Entry Flags Value Print String Match String Validation Display Descriptor */
/* ------------------- ----- ------------ ------------ ---------------- ----------------- ----------------- */
{ MTAB_XDV, 1, NULL, "FASTTIME", &lps_set_timing, NULL, NULL },
{ MTAB_XDV, 0, NULL, "REALTIME", &lps_set_timing, NULL, NULL },
{ MTAB_XDV, 0, "TIMING", NULL, NULL, &lps_show_timing, NULL },
{ MTAB_XDV, 1u, "SC", "SC", &hp_set_dib, &hp_show_dib, (void *) &lps_dib },
{ MTAB_XDV | MTAB_NMO, ~1u, "DEVNO", "DEVNO", &hp_set_dib, &hp_show_dib, (void *) &lps_dib },
{ 0 }
};
static DEBTAB lps_deb [] = {
{ "CMDS", DEB_CMDS },
{ "CPU", DEB_CPU },
{ "XFER", DEB_XFER },
{ "STATE", TRACE_STATE },
{ "IOBUS", TRACE_IOBUS }, /* interface I/O bus signals and data words */
{ NULL, 0 }
};
DEVICE lps_dev = {
"LPS", &lps_unit, lps_reg, lps_mod,
1, 10, 31, 1, 8, 8,
NULL, NULL, &lps_reset,
NULL, &lps_attach, NULL,
&lps_dib, DEV_DISABLE | DEV_DIS | DEV_DEBUG
"LPS", /* device name */
&lps_unit, /* unit array */
lps_reg, /* register array */
lps_mod, /* modifier array */
1, /* number of units */
10, /* address radix */
31, /* address width */
1, /* address increment */
8, /* data radix */
8, /* data width */
NULL, /* examine routine */
NULL, /* deposit routine */
&lps_reset, /* reset routine */
NULL, /* boot routine */
&lps_attach, /* attach routine */
NULL, /* detach routine */
&lps_dib, /* device information block */
DEV_DISABLE | DEV_DIS | DEV_DEBUG, /* device flags */
0, /* debug control flags */
lps_deb, /* debug flag name table */
NULL, /* memory size change routine */
NULL /* logical device name */
};
@@ -288,9 +341,9 @@ DEVICE lps_dev = {
assertion of STC and CLC simultaneously will not.
*/
uint32 lpsio (DIB *dibptr, IOCYCLE signal_set, uint32 stat_data)
static uint32 lpsio (DIB *dibptr, IOCYCLE signal_set, uint32 stat_data)
{
int32 sched;
int32 current_line, current_char;
IOSIGNAL signal;
IOCYCLE working_set = IOADDSIR (signal_set); /* add ioSIR if needed */
@@ -335,18 +388,17 @@ while (working_set) {
lps_sta = LPS_PWROFF;
}
stat_data = IORETURN (SCPE_OK, lps_sta); /* diag, rtn status */
stat_data = IORETURN (SCPE_OK, lps_sta); /* diag, rtn status */
if (DEBUG_PRS (lps_dev))
fprintf (sim_deb, ">>LPS LIx: Status %06o returned\n", lps_sta);
tprintf (lps_dev, DEB_CPU, "Status %06o returned\n", lps_sta);
break;
case ioIOO: /* I/O data output */
lps_unit.buf = IODATA (stat_data);
if (DEBUG_PRS (lps_dev))
fprintf (sim_deb, ">>LPS OTx: Character %06o output\n", lps_unit.buf);
tprintf (lps_dev, DEB_CPU, "Control %06o (%s) output\n",
lps_unit.buf, fmt_char (lps_unit.buf & DATA_MASK));
break;
@@ -381,48 +433,47 @@ while (working_set) {
}
else { /* real lpt, sched */
if (DEBUG_PRS (lps_dev)) fprintf (sim_deb,
">>LPS STC: Character %06o scheduled for line %d, column %d, ",
lps_unit.buf, lps_lcnt + 1, lps_ccnt + 1);
current_char = lps_ccnt + 1;
current_line = lps_lcnt + 1;
if ((lps_unit.buf != '\f') &&
(lps_unit.buf != '\n') &&
(lps_unit.buf != '\r')) { /* normal char */
if ((lps_unit.buf != FF) &&
(lps_unit.buf != LF) &&
(lps_unit.buf != CR)) { /* normal char */
lps_ccnt = lps_ccnt + 1; /* incr char counter */
if (lps_ccnt % LPS_ZONECNT == 0) /* end of zone? */
sched = lps_ptime; /* print zone */
lps_unit.wait = lps_ptime; /* print zone */
else
sched = lps_ctime; /* xfer char */
lps_unit.wait = lps_ctime; /* xfer char */
}
else { /* print cmd */
if (lps_ccnt % LPS_ZONECNT == 0) /* last zone printed? */
sched = lps_ctime; /* yes, so just char time */
lps_unit.wait = lps_ctime; /* yes, so just char time */
else
sched = lps_ptime; /* no, so print needed */
lps_unit.wait = lps_ptime; /* no, so print needed */
lps_ccnt = 0; /* reset char counter */
if (lps_unit.buf == '\n') { /* line advance */
if (lps_unit.buf == LF) { /* line advance */
lps_lcnt = (lps_lcnt + 1) % LPS_PAGELNT;
if (lps_lcnt > 0)
sched = sched + lps_stime;
lps_unit.wait += lps_stime;
else
sched = sched + /* allow for perf skip */
lps_stime * (LPS_FORMLNT - LPS_PAGELNT);
lps_unit.wait += /* allow for perf skip */
lps_stime * (LPS_FORMLNT - LPS_PAGELNT);
}
else if (lps_unit.buf == '\f') { /* form advance */
sched = sched + lps_stime * (LPS_FORMLNT - lps_lcnt);
else if (lps_unit.buf == FF) { /* form advance */
lps_unit.wait += lps_stime * (LPS_FORMLNT - lps_lcnt);
lps_lcnt = 0;
}
}
sim_activate (&lps_unit, sched);
sim_activate (&lps_unit, lps_unit.wait);
if (DEBUG_PRS (lps_dev))
fprintf (sim_deb, "time = %d\n", sched);
tprintf (lps_dev, DEB_CMDS, "Character %s scheduled for line %d, column %d, time = %d\n",
fmt_char (lps_unit.buf & DATA_MASK), current_line, current_char, lps_unit.wait);
}
break;
@@ -450,66 +501,78 @@ return stat_data;
}
/* Unit service */
/* Unit service.
t_stat lps_svc (UNIT *uptr)
As a convenience to the user, the printer output file is flushed when a TOF
operation is performed.
*/
static t_stat lps_svc (UNIT *uptr)
{
int32 c = uptr->buf & 0177;
int32 c = uptr->buf & DATA_MASK;
if (lps_power == LPS_TURNING_ON) { /* printer warmed up? */
lps_power = LPS_ON; /* change state */
lps_restart (uptr, 0, NULL, NULL); /* restart I/O if hung */
if (DEBUG_PRS (lps_dev))
fputs (">>LPS svc: Power state is ON\n", sim_deb);
tprintf (lps_dev, TRACE_STATE, "Power state is ON\n");
return SCPE_OK; /* done */
}
if (uptr->flags & UNIT_DIAG) { /* diagnostic? */
lpsio (&lps_dib, ioENF, 0); /* set flag */
return SCPE_OK; /* done */
}
if ((uptr->flags & UNIT_ATT) == 0) /* attached? */
return IOERROR (lps_stopioe, SCPE_UNATT);
else if (uptr->flags & UNIT_OFFLINE) /* offline? */
return IOERROR (lps_stopioe, STOP_OFFLINE);
else if (uptr->flags & UNIT_POWEROFF) /* powered off? */
return IOERROR (lps_stopioe, STOP_PWROFF);
if ((uptr->flags & (UNIT_ATT | UNIT_OFFLINE | UNIT_POWEROFF)) != UNIT_ATT) /* not ready? */
return SCPE_OK;
lpsio (&lps_dib, ioENF, 0); /* set flag */
if (((c < ' ') || (c > '_')) && /* non-printing char? */
(c != '\f') && (c != '\n') && (c != '\r')) {
if (DEBUG_PRS (lps_dev))
fprintf (sim_deb, ">>LPS svc: Character %06o erased\n", c);
(c != FF) && (c != LF) && (c != CR)) {
tprintf (lps_dev, DEB_XFER, "Character %s erased\n", fmt_char (c));
c = ' '; /* replace with blank */
}
if (lps_ccnt > LPS_PAGECNT) { /* 81st character? */
fputc ('\r', uptr->fileref); /* return to line start */
fputc (CR, uptr->fileref); /* return to line start */
uptr->pos = uptr->pos + 1; /* update pos */
lps_ccnt = 1; /* reset char counter */
if (DEBUG_PRS (lps_dev))
fputs (">>LPS svc: Line wraparound to column 1\n", sim_deb);
tprintf (lps_dev, DEB_XFER, "Line wraparound to column 1\n");
}
fputc (c, uptr->fileref); /* "print" char */
uptr->pos = uptr->pos + 1; /* update pos */
if (DEBUG_PRS (lps_dev))
fprintf (sim_deb, ">>LPS svc: Character %06o printed\n", c);
if ((lps_lcnt == 0) && (c == '\n')) { /* LF did TOF? */
fputc ('\f', uptr->fileref); /* do perf skip */
uptr->pos = uptr->pos + 1; /* update pos */
if (DEBUG_PRS (lps_dev))
fputs (">>LPS svc: Perforation skip to TOF\n", sim_deb);
tprintf (lps_dev, DEB_XFER, "Character %s printed\n", fmt_char (c));
if (lps_lcnt == 0) { /* if the printer is at the TOF */
fflush (uptr->fileref); /* then flush the file buffer for inspection */
if (c == LF) { /* LF did TOF? */
fputc (FF, uptr->fileref); /* do perf skip */
uptr->pos = uptr->pos + 1; /* update pos */
tprintf (lps_dev, DEB_XFER, "Perforation skip to TOF\n");
}
}
if (ferror (uptr->fileref)) {
perror ("LPS I/O error");
clearerr (uptr->fileref);
if (ferror (uptr->fileref)) { /* if a host file I/O error occurred */
cprintf ("%s simulator printer I/O error: %s\n", /* then report the error to the console */
sim_name, strerror (errno));
clearerr (uptr->fileref); /* clear the error */
lps_unit.flags |= UNIT_OFFLINE; /* set offline */
return SCPE_IOERR;
}
return SCPE_OK;
}
/* Reset routine */
t_stat lps_reset (DEVICE *dptr)
static t_stat lps_reset (DEVICE *dptr)
{
if (sim_switches & SWMASK ('P')) { /* power-on reset? */
lps_power = LPS_ON; /* power is on */
@@ -538,7 +601,7 @@ return SCPE_OK;
original I/O request.
*/
t_stat lps_restart (UNIT *uptr, int32 value, CONST char *cptr, void *desc)
static t_stat lps_restart (UNIT *uptr, int32 value, CONST char *cptr, void *desc)
{
if (lps.control && !sim_is_active (uptr))
sim_activate (uptr, 0); /* reschedule I/O */
@@ -547,40 +610,68 @@ return SCPE_OK;
/* Printer power off */
t_stat lps_poweroff (UNIT *uptr, int32 value, CONST char *cptr, void *desc)
static t_stat lps_poweroff (UNIT *uptr, int32 value, CONST char *cptr, void *desc)
{
lps_power = LPS_OFF; /* change state */
if (DEBUG_PRS (lps_dev)) fputs (">>LPS set: Power state is OFF\n", sim_deb);
tprintf (lps_dev, TRACE_STATE, "Power state is OFF\n");
return SCPE_OK;
}
/* Printer power on */
t_stat lps_poweron (UNIT *uptr, int32 value, CONST char *cptr, void *desc)
static t_stat lps_poweron (UNIT *uptr, int32 value, CONST char *cptr, void *desc)
{
if (lps_unit.flags & UNIT_DIAG) { /* diag mode? */
lps_power = LPS_ON; /* no delay */
if (DEBUG_PRS (lps_dev))
fputs (">>LPS set: Power state is ON\n", sim_deb);
tprintf (lps_dev, TRACE_STATE, "Power state is ON\n");
}
else {
lps_power = LPS_TURNING_ON; /* change state */
lps_unit.flags |= UNIT_OFFLINE; /* set offline */
sim_activate (&lps_unit, lps_rtime); /* schedule ready */
if (DEBUG_PRS (lps_dev)) fprintf (sim_deb,
">>LPS set: Power state is TURNING ON, scheduled time = %d\n",
lps_rtime );
tprintf (lps_dev, TRACE_STATE, "Power state is TURNING ON, scheduled time = %d\n",
lps_rtime);
}
return SCPE_OK;
}
/* Attach routine */
/* Attach the printer image file.
t_stat lps_attach (UNIT *uptr, CONST char *cptr)
The specified file is attached to the indicated unit. This is the simulation
equivalent of loading paper into the printer and pressing the ONLINE button.
The transition from offline to online typically generates an interrupt.
A new image file may be requested by giving the "-N" switch to the ATTACH
command. If an existing file is specified with "-N", it will be cleared; if
specified without "-N", printer output will be appended to the end of the
existing file content. In all cases, the paper is positioned at the top of
the form.
Implementation notes:
1. If we are called during a RESTORE command to reattach a file previously
attached when the simulation was SAVEd, the device status and file
position are not altered. This is because SIMH 4.x restores the register
contents before reattaching, while 3.x reattaches before restoring the
registers.
*/
static t_stat lps_attach (UNIT *uptr, CONST char *cptr)
{
lps_ccnt = lps_lcnt = 0; /* top of form */
lps_restart (uptr, 0, NULL, NULL); /* restart I/O if hung */
return attach_unit (uptr, cptr);
t_stat result;
result = hp_attach (uptr, cptr); /* attach the specified printer image file for appending */
if (result == SCPE_OK /* if the attach was successful */
&& (sim_switches & SIM_SW_REST) == 0) { /* and we are not being called during a RESTORE command */
lps_ccnt = 0; /* then clear the character counter */
lps_lcnt = 0; /* and set top of form */
lps_restart (uptr, 0, NULL, NULL); /* restart I/O if hung */
}
return result;
}
/* Set printer timing
@@ -588,7 +679,7 @@ return attach_unit (uptr, cptr);
Realistic timing is factored, depending on CPU model, to account for the
timing method employed by the diagnostic. */
t_stat lps_set_timing (UNIT *uptr, int32 val, CONST char *cptr, void *desc)
static t_stat lps_set_timing (UNIT *uptr, int32 val, CONST char *cptr, void *desc)
{
uint32 i, factor = 1;
@@ -604,7 +695,7 @@ return SCPE_OK;
/* Show printer timing */
t_stat lps_show_timing (FILE *st, UNIT *uptr, int32 val, CONST void *desc)
static t_stat lps_show_timing (FILE *st, UNIT *uptr, int32 val, CONST void *desc)
{
if (lps_timing) fputs ("fast timing", st);
else fputs ("realistic timing", st);

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,31 +1,40 @@
/* hp2100_ms.c: HP 2100 13181A/13183A magnetic tape simulator
/* hp2100_ms.c: HP 2100 13181B/13183B Digital Magnetic Tape Unit Interface 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"),
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.
MS 13181A 7970B 800bpi nine track magnetic tape
13183A 7970E 1600bpi nine track magnetic tape
MS 13181B Digital Magnetic Tape Unit Interface
13183B Digital Magnetic Tape Unit Interface
20-Jul-17 JDB Removed "msc_stopioe" variable and register
11-Jul-17 JDB Renamed "ibl_copy" to "cpu_ibl"
15-Mar-17 JDB Trace flags are now global
Changed DEBUG_PRI calls to tprintfs
13-Mar-17 JDB Deprecated LOCKED/WRITEENABLED for ATTACH -R
10-Mar-17 JDB Added IOBUS to the debug table
27-Feb-17 JDB ibl_copy no longer returns a status code
17-Jan-17 JDB Modified to use "odd_parity" array in hp2100_sys.c
13-May-16 JDB Modified for revised SCP API function parameter types
30-Dec-14 JDB Added S-register parameters to ibl_copy
24-Dec-14 JDB Use T_ADDR_FMT with t_addr values for 64-bit compatibility
@@ -75,18 +84,22 @@
22-Apr-02 RMS Added maximum record length test
References:
- 13181B Digital Magnetic Tape Unit Interface Kit Operating and Service Manual
(13181-90901, Nov-1982)
- 13183B Digital Magnetic Tape Unit Interface Kit Operating and Service Manual
(13183-90901, Nov-1983)
- SIMH Magtape Representation and Handling (Bob Supnik, 30-Aug-2006)
- 13181B Digital Magnetic Tape Unit Interface Kit Operating and Service Manual
(13181-90901, November 1982)
- 13183B Digital Magnetic Tape Unit Interface Kit Operating and Service Manual
(13183-90901, November 1983)
- SIMH Magtape Representation and Handling
(Bob Supnik, 30-Aug-2006)
*/
#include "hp2100_defs.h"
#include "hp2100_cpu.h"
#include "sim_tape.h"
#define UNIT_V_OFFLINE (MTUF_V_UF + 0) /* unit offline */
#define UNIT_OFFLINE (1 << UNIT_V_OFFLINE)
@@ -103,12 +116,6 @@
#define GAP_13183 30 /* gap is 3.0 inches for 13183 cntlr */
#define TCAP (300 * 12 * 800) /* 300 ft capacity at 800 bpi */
/* Debug flags */
#define DEB_CMDS (1 << 0) /* command init and compl */
#define DEB_CPU (1 << 1) /* CPU I/O */
#define DEB_RWS (1 << 2) /* tape reads, writes, status */
/* Command - msc_fnc */
#define FNC_CLR 00110 /* clear */
@@ -180,7 +187,6 @@ int32 msc_sta = 0; /* status */
int32 msc_buf = 0; /* buffer */
int32 msc_usl = 0; /* unit select */
int32 msc_1st = 0; /* first service */
int32 msc_stopioe = 1; /* stop on error */
struct {
FLIP_FLOP control; /* control flip-flop */
@@ -220,12 +226,12 @@ int32 msc_xtime = 0; /* data xfer time / word
typedef int32 TIMESET[6]; /* set of controller times */
int32 *const timers[] = { &msc_btime, &msc_ctime, &msc_gtime,
&msc_itime, &msc_rtime, &msc_xtime };
int32 *const timers [] = { &msc_btime, &msc_ctime, &msc_gtime,
&msc_itime, &msc_rtime, &msc_xtime };
const TIMESET msc_times[3] = {
{ 161512, 14044, 175553, 24885, 878, 88 }, /* 13181A */
{ 252800, 17556, 105333, 27387, 878, 44 }, /* 13183A */
const TIMESET msc_times [3] = {
{ 161512, 14044, 175553, 24885, 878, 88 }, /* 13181B */
{ 252800, 17556, 105333, 27387, 878, 44 }, /* 13183B */
{ 1, 1000, 1, 1, 100, 10 } /* FAST */
};
@@ -284,9 +290,11 @@ REG msd_reg[] = {
{ NULL }
};
MTAB msd_mod[] = {
{ MTAB_XTD | MTAB_VDV, 1, "SC", "SC", &hp_setsc, &hp_showsc, &msd_dev },
{ MTAB_XTD | MTAB_VDV | MTAB_NMO, 1, "DEVNO", "DEVNO", &hp_setdev, &hp_showdev, &msd_dev },
MTAB msd_mod [] = {
/* Entry Flags Value Print String Match String Validation Display Descriptor */
/* ------------------- ----- ------------ ------------ ------------ ------------- ---------------- */
{ MTAB_XDV, 2u, "SC", "SC", &hp_set_dib, &hp_show_dib, (void *) &ms_dib },
{ MTAB_XDV | MTAB_NMO, ~2u, "DEVNO", "DEVNO", &hp_set_dib, &hp_show_dib, (void *) &ms_dib },
{ 0 }
};
@@ -337,46 +345,67 @@ REG msc_reg[] = {
{ DRDATA (RTIME, msc_rtime, 24), REG_NZ + PV_LEFT },
{ DRDATA (XTIME, msc_xtime, 24), REG_NZ + PV_LEFT },
{ FLDATA (TIMING, ms_timing, 0), REG_HRO },
{ FLDATA (STOP_IOE, msc_stopioe, 0) },
{ FLDATA (CTYPE, ms_ctype, 0), REG_HRO },
{ ORDATA (SC, msc_dib.select_code, 6), REG_HRO },
{ ORDATA (DEVNO, msc_dib.select_code, 6), REG_HRO },
{ 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, "CAPACITY", "CAPACITY",
&ms_set_reelsize, &ms_show_reelsize, NULL },
{ MTAB_XTD | MTAB_VUN | MTAB_NMO, 1, "REEL", "REEL",
&ms_set_reelsize, &ms_show_reelsize, NULL },
{ MTAB_XTD | MTAB_VUN, 0, "FORMAT", "FORMAT",
&sim_tape_set_fmt, &sim_tape_show_fmt, NULL },
{ MTAB_XTD | MTAB_VDV, 0, NULL, "13181A",
&ms_settype, NULL, NULL },
{ MTAB_XTD | MTAB_VDV, 1, NULL, "13183A",
&ms_settype, NULL, NULL },
{ MTAB_XTD | MTAB_VDV, 0, "TYPE", NULL,
NULL, &ms_showtype, NULL },
{ MTAB_XTD | MTAB_VDV, 0, NULL, "REALTIME",
&ms_set_timing, NULL, NULL },
{ MTAB_XTD | MTAB_VDV, 1, NULL, "FASTTIME",
&ms_set_timing, NULL, NULL },
{ MTAB_XTD | MTAB_VDV, 0, "TIMING", NULL,
NULL, &ms_show_timing, NULL },
{ MTAB_XTD | MTAB_VDV, 1, "SC", "SC", &hp_setsc, &hp_showsc, &msd_dev },
{ MTAB_XTD | MTAB_VDV | MTAB_NMO, 1, "DEVNO", "DEVNO", &hp_setdev, &hp_showdev, &msd_dev },
/* Modifier list.
The LOCKED and WRITEENABLED modifiers are deprecated. The supported method
of write-protecting a tape drive is to attach the tape image with the -R
(read-only) switch or by setting the host operating system's read-only
attribute on the tape image file. This simulates removing the write ring
from the tape reel before mounting it on the drive. There is no hardware
method of write-protecting a mounted and positioned tape reel.
Implementation notes:
1. The UNIT_RO modifier displays "write ring" if the flag is not set. There
is no corresponding entry for the opposite condition because "read only"
is automatically printed after the attached filename.
*/
MTAB msc_mod [] = {
/* Mask Value Match Value Print String Match String Validation Display Descriptor */
/* ------------- ------------- ---------------- --------------- ------------ ------- ---------- */
{ UNIT_RO, 0, "write ring", NULL, NULL, NULL, NULL },
{ UNIT_OFFLINE, UNIT_OFFLINE, "offline", "OFFLINE", NULL, NULL, NULL },
{ UNIT_OFFLINE, 0, "online", "ONLINE", &msc_online, NULL, NULL },
{ MTUF_WLK, 0, NULL, "WRITEENABLED", NULL, NULL, NULL },
{ MTUF_WLK, MTUF_WLK, NULL, "LOCKED", NULL, NULL, NULL },
/* Entry Flags Value Print String Match String Validation Display Descriptor */
/* ------------------- ----- ------------ ------------ ----------------- ------------------ ---------------- */
{ MTAB_XUN, 0, "CAPACITY", "CAPACITY", &ms_set_reelsize, &ms_show_reelsize, NULL },
{ MTAB_XUN | MTAB_NMO, 1, "REEL", "REEL", &ms_set_reelsize, &ms_show_reelsize, NULL },
{ MTAB_XUN, 0, "FORMAT", "FORMAT", &sim_tape_set_fmt, &sim_tape_show_fmt, NULL },
{ MTAB_XDV, 0, NULL, "13181A/B", &ms_settype, NULL, NULL },
{ MTAB_XDV, 1, NULL, "13183A/B", &ms_settype, NULL, NULL },
{ MTAB_XDV, 0, "TYPE", NULL, NULL, &ms_showtype, NULL },
{ MTAB_XDV, 0, NULL, "REALTIME", &ms_set_timing, NULL, NULL },
{ MTAB_XDV, 1, NULL, "FASTTIME", &ms_set_timing, NULL, NULL },
{ MTAB_XDV, 0, "TIMING", NULL, NULL, &ms_show_timing, NULL },
{ MTAB_XDV, 2u, "SC", "SC", &hp_set_dib, &hp_show_dib, (void *) &ms_dib },
{ MTAB_XDV | MTAB_NMO, ~2u, "DEVNO", "DEVNO", &hp_set_dib, &hp_show_dib, (void *) &ms_dib },
{ 0 }
};
DEBTAB msc_deb[] = {
{ "CMDS", DEB_CMDS },
{ "CPU", DEB_CPU },
{ "RWS", DEB_RWS },
{ NULL, 0 }
{ "CMDS", DEB_CMDS },
{ "RWS", DEB_RWS },
{ "CPU", DEB_CPU },
{ "IOBUS", TRACE_IOBUS }, /* interface I/O bus signals and data words */
{ NULL, 0 }
};
DEVICE msc_dev = {
@@ -554,11 +583,10 @@ while (working_set) {
else
data = data | STA_TBSY | STA_LOCAL;
if (ms_ctype == A13183) /* 13183A? */
if (ms_ctype == A13183) /* 13183? */
data = data | STA_PE | (uint16) (msc_usl << STA_V_SEL);
if (DEBUG_PRI (msc_dev, DEB_CPU))
fprintf (sim_deb, ">>MSC LIx: Status = %06o\n", data);
tprintf (msc_dev, DEB_CPU, "Status = %06o\n", data);
stat_data = IORETURN (SCPE_OK, data); /* merge in return status */
break;
@@ -567,8 +595,7 @@ while (working_set) {
case ioIOO: /* I/O data output */
msc_buf = IODATA (stat_data); /* clear supplied status */
if (DEBUG_PRI (msc_dev, DEB_CPU))
fprintf (sim_deb, ">>MSC OTx: Command = %06o\n", msc_buf);
tprintf (msc_dev, DEB_CPU, "Command = %06o\n", msc_buf);
msc_sta = msc_sta & ~STA_REJ; /* clear reject */
@@ -583,8 +610,7 @@ while (working_set) {
if (msc_buf & FNF_CHS) { /* select change */
msc_usl = map_sel[FNC_GETSEL (msc_buf)]; /* is immediate */
uptr = msc_dev.units + msc_usl;
if (DEBUG_PRI (msc_dev, DEB_CMDS))
fprintf (sim_deb, ">>MSC OTx: Unit %d selected\n", msc_usl);
tprintf (msc_dev, DEB_CMDS, "Unit %d selected\n", msc_usl);
}
if (((msc_buf & FNF_MOT) && sim_is_active (uptr)) ||
@@ -614,8 +640,7 @@ while (working_set) {
working_set = working_set & ~ioCLF; /* eliminate possible CLF */
if (DEBUG_PRI (msc_dev, DEB_CMDS))
fputs (">>MSC STC: Controller cleared\n", sim_deb);
tprintf (msc_dev, DEB_CMDS, "Controller cleared\n");
break; /* command completes immediately */
}
@@ -645,16 +670,14 @@ while (working_set) {
if (msc_buf & ~FNC_SEL) { /* NOP for unit sel alone */
sim_activate (uptr, sched_time); /* else schedule op */
if (DEBUG_PRI (msc_dev, DEB_CMDS))
fprintf (sim_deb,
">>MSC STC: Unit %d command %03o (%s) scheduled, "
"pos = %" T_ADDR_FMT "d, time = %d\n",
msc_usl, uptr->FNC, ms_cmd_name (uptr->FNC),
uptr->pos, sched_time);
tprintf (msc_dev, DEB_CMDS, "Unit %d command %03o (%s) scheduled, "
"pos = %" T_ADDR_FMT "d, time = %d\n",
msc_usl, uptr->FNC, ms_cmd_name (uptr->FNC),
uptr->pos, sched_time);
}
else if (DEBUG_PRI (msc_dev, DEB_CMDS))
fputs (">>MSC STC: Unit select (NOP)\n", sim_deb);
else
tprintf (msc_dev, DEB_CMDS, "Unit select (NOP)\n");
msc_sta = STA_BUSY; /* ctrl is busy */
msc_1st = 1;
@@ -713,7 +736,7 @@ unum = uptr - msc_unit; /* get unit number */
if ((uptr->FNC != FNC_RWS) && (uptr->flags & UNIT_OFFLINE)) { /* offline? */
msc_sta = (msc_sta | STA_REJ) & ~STA_BUSY; /* reject */
mscio (&msc_dib, ioENF, 0); /* set flag */
return IOERROR (msc_stopioe, SCPE_UNATT);
return SCPE_OK;
}
switch (uptr->FNC) { /* case on function */
@@ -741,10 +764,8 @@ switch (uptr->FNC) { /* case on function */
goto DO_WFM; /* do plain file mark */
/* else fall into GAP */
case FNC_GAP: /* erase gap */
if (DEBUG_PRI (msc_dev, DEB_RWS))
fprintf (sim_deb,
">>MSC svc: Unit %d wrote gap\n",
unum);
tprintf (msc_dev, DEB_RWS, "Unit %d wrote gap\n", unum);
r = ms_write_gap (uptr); /* write tape gap*/
if (r || (uptr->FNC != FNC_GFM)) /* if error or not GFM */
@@ -752,10 +773,8 @@ switch (uptr->FNC) { /* case on function */
/* else drop into WFM */
case FNC_WFM: /* write file mark */
if ((ms_timing == 0) && sim_tape_bot (uptr)) { /* realistic timing + BOT? */
if (DEBUG_PRI (msc_dev, DEB_RWS))
fprintf (sim_deb,
">>MSC svc: Unit %d wrote initial gap\n",
unum);
tprintf (msc_dev, DEB_RWS, "Unit %d wrote initial gap\n", unum);
st = ms_write_gap (uptr); /* write initial gap*/
if (st != MTSE_OK) { /* error? */
r = ms_map_err (uptr, st); /* map error */
@@ -763,10 +782,8 @@ switch (uptr->FNC) { /* case on function */
}
}
DO_WFM:
if (DEBUG_PRI (msc_dev, DEB_RWS))
fprintf (sim_deb,
">>MSC svc: Unit %d wrote file mark\n",
unum);
tprintf (msc_dev, DEB_RWS, "Unit %d wrote file mark\n", unum);
st = sim_tape_wrtmk (uptr); /* write tmk */
if (st != MTSE_OK) /* error? */
r = ms_map_err (uptr, st); /* map error */
@@ -808,10 +825,8 @@ switch (uptr->FNC) { /* case on function */
if (msc_1st) { /* first svc? */
msc_1st = ms_ptr = ms_max = 0; /* clr 1st flop */
st = sim_tape_rdrecf (uptr, msxb, &ms_max, DBSIZE); /* read rec */
if (DEBUG_PRI (msc_dev, DEB_RWS))
fprintf (sim_deb,
">>MSC svc: Unit %d read %d word record\n",
unum, ms_max / 2);
tprintf (msc_dev, DEB_RWS, "Unit %d read %d word record\n",
unum, ms_max / 2);
if (st == MTSE_RECE) msc_sta = msc_sta | STA_PAR; /* rec in err? */
else if (st != MTSE_OK) { /* other error? */
r = ms_map_err (uptr, st); /* map error */
@@ -823,7 +838,7 @@ switch (uptr->FNC) { /* case on function */
break; /* err, done */
}
if (ms_ctype == A13183)
msc_sta = msc_sta | STA_ODD; /* set ODD for 13183A */
msc_sta = msc_sta | STA_ODD; /* set ODD for 13183 */
}
if (msd.control && (ms_ptr < ms_max)) { /* DCH on, more data? */
if (msd.flag) msc_sta = msc_sta | STA_TIM | STA_PAR;
@@ -854,10 +869,8 @@ switch (uptr->FNC) { /* case on function */
if (msc_1st) { /* first service? */
msc_1st = ms_ptr = 0; /* no data xfer on first svc */
if ((ms_timing == 0) && sim_tape_bot (uptr)) { /* realistic timing + BOT? */
if (DEBUG_PRI (msc_dev, DEB_RWS))
fprintf (sim_deb,
">>MSC svc: Unit %d wrote initial gap\n",
unum);
tprintf (msc_dev, DEB_RWS, "Unit %d wrote initial gap\n", unum);
st = ms_write_gap (uptr); /* write initial gap */
if (st != MTSE_OK) { /* error? */
r = ms_map_err (uptr, st); /* map error */
@@ -879,10 +892,8 @@ switch (uptr->FNC) { /* case on function */
return SCPE_OK;
}
if (ms_ptr) { /* any data? write */
if (DEBUG_PRI (msc_dev, DEB_RWS))
fprintf (sim_deb,
">>MSC svc: Unit %d wrote %d word record\n",
unum, ms_ptr / 2);
tprintf (msc_dev, DEB_RWS, "Unit %d wrote %d word record\n",
unum, ms_ptr / 2);
st = sim_tape_wrrecf (uptr, msxb, ms_ptr); /* write */
if (st != MTSE_OK) {
r = ms_map_err (uptr, st); /* map error */
@@ -900,19 +911,16 @@ switch (uptr->FNC) { /* case on function */
case FNC_RRR: /* not supported */
default: /* unknown command */
if (DEBUG_PRI (msc_dev, DEB_CMDS))
fprintf (sim_deb,
">>MSC svc: Unit %d command %03o is unknown (NOP)\n",
unum, uptr->FNC);
tprintf (msc_dev, DEB_CMDS, "Unit %d command %03o is unknown (NOP)\n",
unum, uptr->FNC);
break;
}
mscio (&msc_dib, ioENF, 0); /* set flag */
msc_sta = msc_sta & ~STA_BUSY; /* update status */
if (DEBUG_PRI (msc_dev, DEB_CMDS))
fprintf (sim_deb,
">>MSC svc: Unit %d command %03o (%s) complete\n",
unum, uptr->FNC & 0377, ms_cmd_name (uptr->FNC));
tprintf (msc_dev, DEB_CMDS, "Unit %d command %03o (%s) complete\n",
unum, uptr->FNC & 0377, ms_cmd_name (uptr->FNC));
return r;
}
@@ -939,10 +947,7 @@ t_stat ms_map_err (UNIT *uptr, t_stat st)
{
int32 unum = uptr - msc_unit; /* get unit number */
if (DEBUG_PRI (msc_dev, DEB_RWS))
fprintf (sim_deb,
">>MSC err: Unit %d tape library status = %d\n",
unum, st);
tprintf (msc_dev, DEB_RWS, "Unit %d tape library status = %d\n", unum, st);
switch (st) {
@@ -963,7 +968,7 @@ switch (st) {
msc_sta = msc_sta | STA_EOF;
if (ms_ctype == A13181)
msc_sta = msc_sta | STA_ODD; /* EOF also sets ODD for 13181A */
msc_sta = msc_sta | STA_ODD; /* EOF also sets ODD for 13181B */
break;
case MTSE_INVRL: /* invalid rec lnt */
@@ -972,8 +977,7 @@ switch (st) {
case MTSE_IOERR: /* IO error */
msc_sta = msc_sta | STA_PAR; /* error */
if (msc_stopioe) return SCPE_IOERR;
break;
return SCPE_IOERR;
case MTSE_RECE: /* record in error */
msc_sta = msc_sta | STA_PAR; /* error */
@@ -1002,9 +1006,7 @@ for (i = 0; i < MS_NUMDR; i++) { /* look for write in pro
if (sim_is_active (uptr) && /* unit active? */
(uptr->FNC == FNC_WC) && /* and last cmd write? */
(ms_ptr > 0)) { /* and partial buffer? */
if (DEBUG_PRI (msc_dev, DEB_RWS))
fprintf (sim_deb,
">>MSC rws: Unit %d wrote %d word partial record\n", i, ms_ptr / 2);
tprintf (msc_dev, DEB_RWS, "Unit %d wrote %d word partial record\n", i, ms_ptr / 2);
st = sim_tape_wrrecf (uptr, msxb, ms_ptr | MTR_ERF);
@@ -1143,9 +1145,9 @@ return SCPE_OK;
t_stat ms_showtype (FILE *st, UNIT *uptr, int32 val, CONST void *desc)
{
if (ms_ctype == A13183)
fprintf (st, "13183A");
fprintf (st, "13183B");
else
fprintf (st, "13181A");
fprintf (st, "13181B");
return SCPE_OK;
}
@@ -1313,9 +1315,8 @@ const int32 dev = msd_dib.select_code; /* get data chan device
if (unitno != 0) /* boot supported on drive unit 0 only */
return SCPE_NOFNC; /* report "Command not allowed" if attempted */
if (ibl_copy (ms_rom, dev, IBL_OPT, /* copy the boot ROM to memory and configure */
IBL_MS | IBL_SET_SC (dev))) /* the S register accordingly */
return SCPE_IERR; /* return an internal error if the copy failed */
cpu_ibl (ms_rom, dev, IBL_OPT, /* copy the boot ROM to memory and configure */
IBL_MS | IBL_SET_SC (dev)); /* the S register accordingly */
if ((sim_switches & SWMASK ('S')) && AR) /* if -S is specified and the A register is non-zero */
SR = SR | 1; /* then set to skip to the file number in A */
@@ -1325,32 +1326,10 @@ return SCPE_OK;
/* Calculate tape record CRC and LRC characters */
#define E 0400 /* parity bit for odd parity */
#define O 0000 /* parity bit for odd parity */
static const uint16 odd_parity [256] = { /* parity table */
E, O, O, E, O, E, E, O, O, E, E, O, E, O, O, E, /* 000-017 */
O, E, E, O, E, O, O, E, E, O, O, E, O, E, E, O, /* 020-037 */
O, E, E, O, E, O, O, E, E, O, O, E, O, E, E, O, /* 040-067 */
E, O, O, E, O, E, E, O, O, E, E, O, E, O, O, E, /* 060-077 */
O, E, E, O, E, O, O, E, E, O, O, E, O, E, E, O, /* 100-117 */
E, O, O, E, O, E, E, O, O, E, E, O, E, O, O, E, /* 120-137 */
E, O, O, E, O, E, E, O, O, E, E, O, E, O, O, E, /* 140-157 */
O, E, E, O, E, O, O, E, E, O, O, E, O, E, E, O, /* 160-177 */
O, E, E, O, E, O, O, E, E, O, O, E, O, E, E, O, /* 200-217 */
E, O, O, E, O, E, E, O, O, E, E, O, E, O, O, E, /* 220-237 */
E, O, O, E, O, E, E, O, O, E, E, O, E, O, O, E, /* 240-267 */
O, E, E, O, E, O, O, E, E, O, O, E, O, E, E, O, /* 260-277 */
E, O, O, E, O, E, E, O, O, E, E, O, E, O, O, E, /* 300-317 */
O, E, E, O, E, O, O, E, E, O, O, E, O, E, E, O, /* 320-337 */
O, E, E, O, E, O, O, E, E, O, O, E, O, E, E, O, /* 340-357 */
E, O, O, E, O, E, E, O, O, E, E, O, E, O, O, E /* 360-377 */
};
static uint32 calc_crc_lrc (uint8 *buffer, t_mtrlnt length)
{
uint32 i;
uint16 byte, crc, lrc;
HP_WORD byte, crc, lrc;
lrc = crc = 0;

View File

@@ -1,30 +1,33 @@
/* hp2100_mt.c: HP 2100 12559A magnetic tape simulator
/* hp2100_mt.c: HP 2100 12559C 9-Track Magnetic Tape Unit Interface
Copyright (c) 1993-2016, Robert M. Supnik
Copyright (c) 2017, J. David Bryan
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
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
AUTHORS 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.
MT 12559A 3030 nine track magnetic tape
MT 12559C 9-Track Magnetic Tape Unit Interface
20-Jul-17 JDB Removed "mtc_stopioe" variable and register
13-Mar-17 JDB Deprecated LOCKED/WRITEENABLED for ATTACH -R
13-May-16 JDB Modified for revised SCP API function parameter types
24-Dec-14 JDB Added casts for explicit downward conversions
10-Jan-13 MP Added DEV_TAPE to DEVICE flags
@@ -58,9 +61,10 @@
04-Oct-98 RMS V2.4 magtape format
References:
- 12559A 9-Track Magnetic Tape Unit Interface Kit Operating and Service Manual
(12559-9001, Jul-1970)
- SIMH Magtape Representation and Handling (Bob Supnik, 30-Aug-2006)
- 12559A 9-Track Magnetic Tape Unit Interface Kit Operating and Service Manual
(12559-9001, July 1970)
- SIMH Magtape Representation and Handling
(Bob Supnik, 30-Aug-2006)
The 3030 was one of HP's earliest tape drives. The 12559A controller
@@ -76,6 +80,7 @@
feature of the 12578A DMA card for the 2116 computer. The second meant that
software drivers had to pad short records with blanks or nulls.
Implementation notes:
1. The HP 3030 Magnetic Tape Subsystem diagnostic, part number 20433-60001,
@@ -84,9 +89,12 @@
*/
#include "hp2100_defs.h"
#include "sim_tape.h"
#define DB_V_SIZE 16 /* max data buf */
#define DBSIZE (1 << DB_V_SIZE) /* max data cmd */
@@ -132,7 +140,6 @@ int32 mtc_1st = 0; /* first svc flop */
int32 mtc_ctime = 40; /* command wait */
int32 mtc_gtime = 1000; /* gap stop time */
int32 mtc_xtime = 15; /* data xfer time */
int32 mtc_stopioe = 1; /* stop on error */
uint8 mtxb[DBSIZE] = { 0 }; /* data buffer */
t_mtrlnt mt_ptr = 0, mt_max = 0; /* buffer ptrs */
static const uint32 mtc_cmd[] = {
@@ -180,8 +187,10 @@ REG mtd_reg[] = {
};
MTAB mtd_mod[] = {
{ MTAB_XTD | MTAB_VDV, 1, "SC", "SC", &hp_setsc, &hp_showsc, &mtd_dev },
{ MTAB_XTD | MTAB_VDV | MTAB_NMO, 1, "DEVNO", "DEVNO", &hp_setdev, &hp_showdev, &mtd_dev },
/* Entry Flags Value Print String Match String Validation Display Descriptor */
/* ------------------- ----- ------------ ------------ ------------ ------------- ---------------- */
{ MTAB_XDV, 2u, "SC", "SC", &hp_set_dib, &hp_show_dib, (void *) &mt_dib },
{ MTAB_XDV | MTAB_NMO, ~2u, "DEVNO", "DEVNO", &hp_set_dib, &hp_show_dib, (void *) &mt_dib },
{ 0 }
};
@@ -216,19 +225,47 @@ REG mtc_reg[] = {
{ DRDATA (CTIME, mtc_ctime, 24), REG_NZ + PV_LEFT },
{ DRDATA (GTIME, mtc_gtime, 24), REG_NZ + PV_LEFT },
{ DRDATA (XTIME, mtc_xtime, 24), REG_NZ + PV_LEFT },
{ FLDATA (STOP_IOE, mtc_stopioe, 0) },
{ ORDATA (SC, mtc_dib.select_code, 6), REG_HRO },
{ ORDATA (DEVNO, mtc_dib.select_code, 6), REG_HRO },
{ NULL }
};
MTAB mtc_mod[] = {
{ MTUF_WLK, 0, "write enabled", "WRITEENABLED", NULL },
{ MTUF_WLK, MTUF_WLK, "write locked", "LOCKED", NULL },
{ MTAB_XTD | MTAB_VDV, 0, "FORMAT", "FORMAT",
&sim_tape_set_fmt, &sim_tape_show_fmt, NULL },
{ MTAB_XTD | MTAB_VDV, 1, "SC", "SC", &hp_setsc, &hp_showsc, &mtd_dev },
{ MTAB_XTD | MTAB_VDV | MTAB_NMO, 1, "DEVNO", "DEVNO", &hp_setdev, &hp_showdev, &mtd_dev },
/* Modifier list.
The LOCKED and WRITEENABLED modifiers are deprecated. The supported method
of write-protecting a tape drive is to attach the tape image with the -R
(read-only) switch or by setting the host operating system's read-only
attribute on the tape image file. This simulates removing the write ring
from the tape reel before mounting it on the drive. There is no hardware
method of write-protecting a mounted and positioned tape reel.
Implementation notes:
1. The UNIT_RO modifier displays "write ring" if the flag is not set. There
is no corresponding entry for the opposite condition because "read only"
is automatically printed after the attached filename.
2. FORMAT is really a unit option, but as there is only one unit, it is
specified as MTAB_XDV so that SHOW MTC FORMAT is accepted, rather than
requiring SHOW MTC0 FORMAT.
*/
MTAB mtc_mod [] = {
/* Mask Value Match Value Print String Match String Validation Display Descriptor */
/* ------------- ------------- ---------------- --------------- ------------ ------- ---------- */
{ UNIT_RO, 0, "write ring", NULL, NULL, NULL, NULL },
{ MTUF_WLK, 0, NULL, "WRITEENABLED", NULL, NULL, NULL },
{ MTUF_WLK, MTUF_WLK, NULL, "LOCKED", NULL, NULL, NULL },
/* Entry Flags Value Print String Match String Validation Display Descriptor */
/* ------------------- ----- ------------ ------------ ----------------- ------------------ ---------------- */
{ MTAB_XDV, 0, "FORMAT", "FORMAT", &sim_tape_set_fmt, &sim_tape_show_fmt, NULL },
{ MTAB_XDV, 2u, "SC", "SC", &hp_set_dib, &hp_show_dib, (void *) &mt_dib },
{ MTAB_XDV | MTAB_NMO, ~2u, "DEVNO", "DEVNO", &hp_set_dib, &hp_show_dib, (void *) &mt_dib },
{ 0 }
};
@@ -484,7 +521,7 @@ t_stat st, r = SCPE_OK;
if ((mtc_unit.flags & UNIT_ATT) == 0) { /* offline? */
mtc_sta = STA_LOCAL | STA_REJ; /* rejected */
mtcio (&mtc_dib, ioENF, 0); /* set cch flg */
return IOERROR (mtc_stopioe, SCPE_UNATT);
return SCPE_OK;
}
switch (mtc_fnc) { /* case on function */
@@ -603,7 +640,7 @@ switch (st) {
case MTSE_IOERR: /* IO error */
mtc_sta = mtc_sta | STA_PAR; /* error */
if (mtc_stopioe) return SCPE_IOERR;
return SCPE_IOERR;
break;
case MTSE_INVRL: /* invalid rec lnt */

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
/* hp2100_pif.c: HP 12620A/12936A privileged interrupt fence simulator
/* hp2100_pif.c: HP 12620A/12936A Privileged Interrupt Fence 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"),
@@ -23,8 +23,11 @@
used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from the author.
PIF 12620A/12936A privileged interrupt fence
PIF 12620A/12936A Privileged Interrupt Fence
15-Mar-17 JDB Trace flags are now global
11-Mar-17 JDB Revised the trace outputs
17-Jan-17 JDB Changed "hp_---sc" and "hp_---dev" to "hp_---_dib"
13-May-16 JDB Modified for revised SCP API function parameter types
10-Feb-12 JDB Deprecated DEVNO in favor of SC
28-Mar-11 JDB Tidied up signal handling
@@ -33,10 +36,10 @@
18-Jun-08 JDB Created PIF device
References:
- 12620A Breadboard Interface Kit Operating and Service Manual
(12620-90001, May-1978)
- 12936A Privileged Interrupt Fence Accessory Installation and Service Manual
(12936-90001, Mar-1974)
- 12620A Breadboard Interface Kit Operating and Service Manual
(12620-90001, May 1978)
- 12936A Privileged Interrupt Fence Accessory Installation and Service Manual
(12936-90001, March 1974)
The Privileged Interupt Fence (PIF) was used in DOS and RTE systems to
@@ -95,9 +98,11 @@
*/
#include "hp2100_defs.h"
/* Device flags */
#define DEV_V_12936 (DEV_V_UF + 0) /* 12936A card */
@@ -158,14 +163,26 @@ REG pif_reg [] = {
};
MTAB pif_mod [] = {
{ MTAB_XTD | MTAB_VDV, 0, NULL, "12620A", &pif_set_card, NULL, NULL },
{ MTAB_XTD | MTAB_VDV, 1, NULL, "12936A", &pif_set_card, NULL, NULL },
{ MTAB_XTD | MTAB_VDV, 0, "TYPE", NULL, NULL, &pif_show_card, NULL },
{ MTAB_XTD | MTAB_VDV, 0, "SC", "SC", &hp_setsc, &hp_showsc, &pif_dev },
{ MTAB_XTD | MTAB_VDV | MTAB_NMO, 0, "DEVNO", "DEVNO", &hp_setdev, &hp_showdev, &pif_dev },
/* Entry Flags Value Print String Match String Validation Display Descriptor */
/* ------------------- ----- ------------ ------------ -------------- -------------- ----------------- */
{ MTAB_XDV, 0, NULL, "12620A", &pif_set_card, NULL, NULL },
{ MTAB_XDV, 1, NULL, "12936A", &pif_set_card, NULL, NULL },
{ MTAB_XDV, 0, "TYPE", NULL, NULL, &pif_show_card, NULL },
{ MTAB_XDV, 1u, "SC", "SC", &hp_set_dib, &hp_show_dib, (void *) &pif_dib },
{ MTAB_XDV | MTAB_NMO, ~1u, "DEVNO", "DEVNO", &hp_set_dib, &hp_show_dib, (void *) &pif_dib },
{ 0 }
};
/* Debugging trace list */
static DEBTAB pif_deb [] = {
{ "CMD", TRACE_CMD }, /* interface commands */
{ "IOBUS", TRACE_IOBUS }, /* interface I/O bus signals and data words */
{ NULL, 0 }
};
DEVICE pif_dev = {
"PIF", /* device name */
&pif_unit, /* unit array */
@@ -186,7 +203,7 @@ DEVICE pif_dev = {
&pif_dib, /* device information block */
DEV_DEBUG | DEV_DISABLE, /* device flags */
0, /* debug control flags */
NULL, /* debug flag name table */
pif_deb, /* debug flag name table */
NULL, /* memory size change routine */
NULL }; /* logical device name */
@@ -218,9 +235,7 @@ DEVICE pif_dev = {
uint32 pif_io (DIB *dibptr, IOCYCLE signal_set, uint32 stat_data)
{
const char *hold_or_clear = (signal_set & ioCLF ? ",C" : "");
const t_bool is_rte_pif = (pif_dev.flags & DEV_12936) == 0;
IOSIGNAL signal;
IOCYCLE working_set = IOADDSIR (signal_set); /* add ioSIR if needed */
@@ -231,19 +246,13 @@ while (working_set) {
case ioCLF: /* clear flag flip-flop */
pif.flag = pif.flagbuf = CLEAR; /* clear flag buffer and flag */
if (DEBUG_PRS (pif_dev))
fputs (">>PIF: [CLF] Flag cleared\n", sim_deb);
break;
case ioSTF: /* set flag flip-flop */
if (is_rte_pif) { /* RTE PIF? */
if (is_rte_pif) /* RTE PIF? */
pif.flag = pif.flagbuf = SET; /* set flag buffer and flag */
if (DEBUG_PRS (pif_dev))
fputs (">>PIF: [STF] Flag set\n", sim_deb);
}
break;
@@ -263,9 +272,6 @@ while (working_set) {
if (!is_rte_pif) { /* DOS PIF? */
pif.flag = pif.flagbuf = SET; /* set flag buffer and flag */
working_set = working_set | ioSIR; /* set SIR (not normally done for IOO) */
if (DEBUG_PRS (pif_dev))
fprintf (sim_deb, ">>PIF: [OTx%s] Flag set\n", hold_or_clear);
}
break;
@@ -274,27 +280,22 @@ while (working_set) {
pif.flag = pif.flagbuf = /* set or clear flag and flag buffer */
(is_rte_pif ? SET : CLEAR);
if (DEBUG_PRS (pif_dev))
fprintf (sim_deb, ">>PIF: [POPIO] Flag %s\n",
(is_rte_pif ? "set" : "cleared"));
tprintf (pif_dev, TRACE_CMD, "Power-on reset\n");
break;
case ioCRS: /* control reset */
tprintf (pif_dev, TRACE_CMD, "Control reset\n");
/* fall into ioCLC handler */
case ioCLC: /* clear control flip-flop */
pif.control = CLEAR; /* clear control */
if (DEBUG_PRS (pif_dev))
fprintf (sim_deb, ">>PIF: [%s%s] Control cleared\n",
(signal == ioCRS ? "CRS" : "CLC"), hold_or_clear);
break;
case ioSTC: /* set control flip-flop */
pif.control = SET; /* set control */
if (DEBUG_PRS (pif_dev))
fprintf (sim_deb, ">>PIF: [STC%s] Control set\n", hold_or_clear);
break;
@@ -310,10 +311,9 @@ while (working_set) {
setIRQ (dibptr->select_code, !pif.control & pif.flag & pif.flagbuf);
}
if (DEBUG_PRS (pif_dev))
fprintf (sim_deb, ">>PIF: [SIR] PRL = %d, IRQ = %d\n",
PRL (dibptr->select_code),
IRQ (dibptr->select_code));
tprintf (pif_dev, TRACE_CMD, "Fence %s%s lower-priority interrupts\n",
(IRQ (dibptr->select_code) ? "requests an interrupt and " : ""),
(PRL (dibptr->select_code) ? "allows" : "inhibits"));
break;

View File

@@ -1,6 +1,6 @@
SIMH/HP 2100 RELEASE NOTES
==========================
Last update: 2017-05-01
Last update: 2017-09-06
This file documents the release history of the simulator for the Hewlett-Packard
@@ -157,6 +157,282 @@ Revision 5010:
======================
Release 27, 2017-09-06
======================
This release of the HP 2100 simulator adds the following features:
- Support for the HP 2613, 2617, and 2618 line printers has been added to the
LPT device. The default printer remains the HP 2607.
- The LPT device simulation has been rewritten to support realistic and
optimized timing, compact and expanded output modes, custom VFU tape images,
and tracing of internal operations.
- The LOAD command has been rewritten to load files containing absolute binary
loaders into the protected address space of the 21xx machines and configure
the I/O instructions. For the 1000, LOAD can also be used to load boot
loader ROM images other than those provided directly by the simulator.
- The DUMP command has been added to write the binary loader currently resident
in memory to an absolute binary file.
- The TTY punch unit and the LPS, LPT, and PTP devices now position a newly
attached file at the end of the file rather than at the start. As a result,
output will append to, rather than overwrite, the existing content.
- The DA, DP, DQ, and DS disc devices add the PROTECT and UNPROTECT options.
These replace the now-deprecated LOCKED and WRITEENABLED options and more
accurately reflect the labelling of the data protection switches on the disc
drives.
- The simulator message that is displayed when a programmed halt occurs has
been changed to indicate that the halt code comes from the T-register value.
- The Basic Binary Loader (BBL) is now installed by default in the 21xx
machines. It is automatically configured to the select code of the paper
tape reader. It may be overwritten with a different loader (e.g., the Basic
Binary Disc Loader or Basic Moving-head Disc Loader) using the LOAD command.
Performing a power-on reset of the CPU reinstalls the BBL.
- Symbolic display and entry has been rewritten to improve efficiency and
expanded to cover the full instruction set including optional microcode
extensions that are currently enabled.
- CPU instruction execution and data accesses may be selectively traced. The
resulting trace listing is similar to the output of a logic analyzer
connected to the CPU and I/O buses.
- DMA/DCPC commands, status, and data accesses may be selectively traced.
- TBG commands, status, and service entries may be selectively traced.
- The DIAG option of the TBG device has been replaced with the REALTIME, W1A,
W1B, W2A, and W2B options. Configuring the TBG to run its diagnostic now
uses the REALTIME and W2B options, and restoring the normal configuration
uses the CALTIME and W2A options. The W1A and W1B options extend the
software compatibility of the TBG.
- The MUXM device has been renamed MUXC to reflect that it is the multiplexer
control card. The previous MUXM name is deprecated but will still work in
existing simulation command files.
- The multiplexer control card (MUXC) may be enabled and disabled independently
of the upper and lower data cards (MUX and MUXL), reflecting its optional
status in hardware configurations.
- Memory address parsing for commands has been changed to add <page>.<offset>
format for physical addresses, where both the page and the offset range from
0 to 1777 octal. Linear addressing is now restricted to the 32K logical
address space (0 to 77777 octal). Memory display uses linear addressing for
locations within the logical address space; locations above 32K use the
physical address format.
- The previously separate STOP_INST, STOP_DEV, STOP_IOE, and INDMAX
pseudo-registers used to stop the simulator under certain conditions have
been replaced by the SET CPU STOP=<stopname>[,<stopname>...] and the SET CPU
INDIR=<limit> commands. Stops may be temporarily bypassed by adding the -B
switch to the command that resumes execution.
- The HP 2100 Simulator User's Guide has been rewritten and significantly
expanded.
--------------------
Implementation Notes
--------------------
- The simulator passes the HP 2613/17/18 line printer diagnostic as described
in the "hp2100_diag.txt" file.
- The line printer terminates each print line with the HP-standard CR/LF pair.
If the output file is to be retained as a text file on a Unix system, removal
of the carriage returns, e.g., via the "dos2unix" utility, may be desirable.
- The LOAD command can no longer be used to read general absolute binary paper
tape images into memory. The ATTACH PTR and BOOT PTR commands must now be
used to read paper tapes.
- The OS, OSTBG, VMA, EMA, VIS, and SIGNAL CPU debug flags have been removed.
Tracing of these firmware instructions is now performed by specifying SET CPU
DEBUG=EXEC and SET CPU EXEC with the appropriate opcode range and mask, as
follows:
* SET CPU DEBUG=OS => SET CPU EXEC=105340;177760
* SET CPU DEBUG=VMA => SET CPU EXEC=105240;177760
* SET CPU DEBUG=EMA => SET CPU EXEC=105240;177760
* SET CPU DEBUG=VIS => SET CPU EXEC=101460;173760
* SET CPU DEBUG=SIGNAL => SET CPU EXEC=105600;177760
- The separate tracing of time-base generator interrupt instructions provided
by the OS and OSTBG CPU debug flags is no longer supported. Entering the
replacement command above traces all OS instructions, including the TBG
interrupt instructions.
- The TIMER, RRR 16, .FLUN, and the OS/VMA, VIS, and SIGNAL self-test
instructions are no longer exempt from the undefined/unimplemented
instruction stop tests. Attempted execution of these instructions without
the appropriate firmware options installed will cause simulation stops if the
UNDEF (TIMER and RRR) or UNIMPL (.FLUN and self-tests) option is enabled.
Because of this change, the default state of the unimplemented instruction
stop has been reversed from "on" to "off".
- The "stop on I/O error" features controlled by the STOP_IOE register values
have been removed from the DR, LPS, LPT, MSC, MTC, and PTP devices, as all of
these report I/O error status to the CPU via their interface input registers.
STOP_IOE has been removed from the PTR device and replaced with SET CPU
STOP=IOERR, as this device does not report I/O error status to the CPU
through its interface.
- The LOCKED and WRITEENABLED options for the MSC and MTC devices are
deprecated. The supported method of write-protecting a tape drive is to
attach the tape image with the -R (read-only) switch or by setting the host
operating system's read-only attribute on the tape image file. This
simulates removing the write ring from the tape reel before mounting it on
the drive. There is no hardware method of write-protecting a mounted and
positioned tape reel.
- If the previous ATTACH behavior (overwriting rather than appending) is
desired for the TTY punch unit and the LPS, LPT, and PTP devices, set the
device's (P)POS register to 0 after attaching.
----------
Bugs Fixed
----------
1. PROBLEM: EXAMINE -M for addresses > 32K displays misleading operands.
VERSION: Release 26.
OBSERVATION: Current-page memory references of instructions residing above
the 32K logical address space are printed as though they reside at their
locations modulo 32K. For example, DEPOSIT 170001 026020 and EXAMINE -M
170001 displays JMP 70020, and DEPOSIT 200001 026020 displays JMP 20.
CAUSE: The printed addresses assume that the instructions will be executed
from their respective pages (modulo 32). However, instructions can be
executed only when they are mapped into the logical address space, and any
given physical page may be mapped to any arbitrary logical page.
Therefore, the address printed may not represent the actual logical address
after mapping.
RESOLUTION: Modify "fprint_cpu" (hp2100_sys.c) to use Z/C address notation
for memory references in instructions residing in physical memory above
32K.
STATUS: Fixed in Release 27.
2. PROBLEM: Enabling IOP firmware should not be allowed on the 1000 F-Series.
VERSION: Release 26.
OBSERVATION: The command "SET CPU 1000-F,IOP" is allowed, but it should
not be, as the IOP firmware is not supported on this machine.
CAUSE: The F-Series does not provide the firmware mapping table entries
that permit operation of the 2000/Access I/O Processor firmware. IOP
instruction opcodes 10x400-17 and 10x420-37 are marked as "HP Reserved" in
the F-Series mapping table, and opcodes 10x460-77 are dedicated to the VIS
microcode.
RESOLUTION: Modify the "cpu_features" array (hp2100_cpu.c) to remove the
IOP option from the 1000 F-Series entry.
STATUS: Fixed in Release 27.
3. PROBLEM: A rejected model change still changes the CPU options.
VERSION: Release 26.
OBSERVATION: Changing to a CPU model that does not support the current
memory size will reduce memory to the maximum supported by the new model.
If the truncated portion contains non-zero values, the simulator will ask
for confirmation before proceeding. If the truncation is rejected, the CPU
options are still set to those of the new model, even though the old model
is retained. For example:
sim> SET CPU 1000-F,128K
sim> SHOW CPU
CPU idle disabled
128KW, 1000-F, EAU
FP, no IOP, DMS
FFP, DBI, no EMA/VMA
no VIS, no SIGNAL
sim> DEPOSIT 100000 1
sim> SET CPU 2116
Really truncate memory [N]?NO
Command not completed
sim> SHOW CPU
CPU idle disabled
128KW, 1000-F, no EAU
no FP, no IOP, no DMS
no FFP, no DBI, no EMA/VMA
no VIS, no SIGNAL
CAUSE: The CPU options are set before the memory size is changed, so when
the size change is rejected, the new CPU options are retained.
RESOLUTION: Modify "cpu_set_model" (hp2100_cpu.c) to perform the memory
size change first, so that if it is rejected, the CPU options have not been
changed.
STATUS: Fixed in Release 27.
4. PROBLEM: Virtual memory mapping fails for accesses above 126 MB.
VERSION: Release 26.
OBSERVATION: A program using virtual memory provided by the RTE-6/VM
operating system may access up to 128 MB of data, although VMA programs
default to a 16 MB limit. Accesses to data in virtual memory are mapped
through the last two DMS user map registers. Normally, each VMA access
maps in the memory page corresponding to the virtual address plus the
following memory page. This allows access to single items up to 1024 words
in size starting at any offset within the (first) page.
If a data item resides in the last 2 MB of virtual memory, access to an
item that crosses the page boundary is incorrect. Instead of accessing
words in the second page, the accesses wrap around within the first page.
CAUSE: The suit number part of the virtual address is not restored before
checking the allocation status of the page table entry corresponding to the
second (spillover) page. As a result, an unallocated second page in the
last 2 MB of virtual memory is seen as beyond the VM area limit, and
instead of generating a page fault to allocate the second page, the map
registers are set up to prevent access to the second page by setting the
first page address into both map registers.
RESOLUTION: Modify "cpu_vma_lbp" (hp2100_cpu5.c) to check for spill page
allocation correctly.
STATUS: Fixed in Release 27.
5. PROBLEM: Memory expansion is not disabled when DMS is disabled.
VERSION: Release 26.
OBSERVATION: If the Memory Expansion Module in a 1000-Series CPU has been
enabled, and then the DMS firmware option is disabled or the CPU is changed
to a model that does not support memory expansion (e.g., a 2100), memory
expansion remains enabled. In this case, memory accesses should revert to
physical addressing, but instead logical-to-physical address translation
through the currently enabled map remains in effect.
CAUSE: Disabling DMS should set the "dms_enb" flag to 0, but it does not.
RESOLUTION: Modify "set_model" and "set_option" (hp2100_cpu.c) to clear
the "dms_enb" flag if DMS is not enabled after the model or option change.
STATUS: Fixed in Release 27.
======================
Release 26, 2017-05-01
======================

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

Binary file not shown.