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:
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
7729
HP2100/hp2100_cpu.c
7729
HP2100/hp2100_cpu.c
File diff suppressed because it is too large
Load Diff
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 */
|
||||
|
||||
1703
HP2100/hp2100_cpu5.c
1703
HP2100/hp2100_cpu5.c
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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)
|
||||
-----------------------------------------------------
|
||||
|
||||
@@ -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 */
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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 */
|
||||
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
2230
HP2100/hp2100_lpt.c
2230
HP2100/hp2100_lpt.c
File diff suppressed because it is too large
Load Diff
3079
HP2100/hp2100_mpx.c
3079
HP2100/hp2100_mpx.c
File diff suppressed because it is too large
Load Diff
@@ -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;
|
||||
|
||||
|
||||
@@ -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
@@ -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;
|
||||
|
||||
|
||||
|
||||
@@ -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
5701
HP2100/hp2100_sys.c
5701
HP2100/hp2100_sys.c
File diff suppressed because it is too large
Load Diff
Binary file not shown.
Reference in New Issue
Block a user