1
0
mirror of https://github.com/open-simh/simh.git synced 2026-02-28 17:29:55 +00:00

HP3000: HP 3000 release 7

See HP3000/hp3000_release.txt for details of the release
This commit is contained in:
Mark Pizzolato
2018-01-12 15:06:04 -08:00
parent 0dc94bf3ec
commit 5f94c22f00
13 changed files with 815 additions and 362 deletions

View File

@@ -1,6 +1,6 @@
/* hp3000_atc.c: HP 3000 30032B Asynchronous Terminal Controller simulator
Copyright (c) 2014-2016, J. David Bryan
Copyright (c) 2014-2017, J. David Bryan
Copyright (c) 2002-2012, Robert M Supnik
Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -26,6 +26,10 @@
ATCD,ATCC HP 30032B Asynchronous Terminal Controller
18-Dec-17 JDB Return event time instead of status from "activate_unit"
11-Dec-17 JDB Reschedule "line_service" if receive buffer has data
26-Oct-17 JDB Call "tmxr_poll_tx" if transmit buffer is full
05-Sep-17 JDB Changed REG_A (permit any symbolic override) to REG_X
16-Sep-16 JDB Fixed atcd_detach to skip channel cancel if SIM_SW_REST
12-Sep-16 JDB Changed DIB register macro usage from SRDATA to DIB_REG
20-Jul-16 JDB Corrected poll_unit "wait" field initializer.
@@ -782,7 +786,7 @@ static void tci_master_reset (void);
static t_stat line_service (UNIT *uptr);
static t_stat poll_service (UNIT *uptr);
static t_stat activate_unit (UNIT *uptr, ACTIVATOR reason);
static int32 activate_unit (UNIT *uptr, ACTIVATOR reason);
static uint32 service_time (HP_WORD control, ACTIVATOR reason);
static void store (HP_WORD control, HP_WORD data);
static void receive (int32 channel, int32 data, t_bool loopback);
@@ -926,17 +930,17 @@ static REG atcd_reg [] = {
/* ------ ------ ------------------- ----- ----- ------ ---------------- --------------- */
{ ORDATA (CNTL, tdi_control_word, 16), REG_FIT },
{ ORDATA (STAT, tdi_status_word, 16), REG_FIT },
{ ORDATA (READ, tdi_read_word, 16), REG_A | REG_FIT },
{ ORDATA (WRITE, tdi_write_word, 16), REG_A | REG_FIT },
{ ORDATA (READ, tdi_read_word, 16), REG_X | REG_FIT },
{ ORDATA (WRITE, tdi_write_word, 16), REG_X | REG_FIT },
{ FLDATA (FLAG, tdi_data_flag, 0) },
{ FLDATA (MASK, tdi_interrupt_mask, 0) },
{ DRDATA (FTIME, fast_data_time, 24), PV_LEFT },
{ BRDATA (RSTAT, recv_status, 8, 16, RECV_CHAN_COUNT) },
{ BRDATA (RPARM, recv_param, 8, 16, RECV_CHAN_COUNT) },
{ BRDATA (RBUFR, recv_buffer, 8, 16, RECV_CHAN_COUNT), REG_A },
{ BRDATA (RBUFR, recv_buffer, 8, 16, RECV_CHAN_COUNT), REG_X },
{ BRDATA (SSTAT, send_status, 8, 16, SEND_CHAN_COUNT) },
{ BRDATA (SPARM, send_param, 8, 16, SEND_CHAN_COUNT) },
{ BRDATA (SBUFR, send_buffer, 8, 16, SEND_CHAN_COUNT), REG_A },
{ BRDATA (SBUFR, send_buffer, 8, 16, SEND_CHAN_COUNT), REG_X },
{ FLDATA (POLL, atc_is_polling, 0), REG_HRO },
DIB_REGS (atcd_dib),
@@ -1723,6 +1727,7 @@ tdi_master_reset (); /* perform a master rese
if (sim_switches & SWMASK ('P')) { /* if this is a power-on reset */
sim_rtcn_init (poll_unit.wait, TMR_ATC); /* then initialize the poll timer */
fast_data_time = FAST_IO_TIME; /* restore the initial fast data time */
atcd_ldsc [0].xmte = 1; /* enable transmission on the system console port */
}
if (atc_is_polling) { /* if we're polling for the simulation console */
@@ -1825,6 +1830,14 @@ return status;
unit 16 if it is attached. In all cases, it is imperative that we not reject
the request for unit 16; otherwise any remaining device detaches will not be
performed.
Implementation notes:
1. Detaching the multiplexer resets each line first, which flushes the
output buffer. This ensures that buffered data that has not been output
via a poll_service entry before the DETACH command was issued is written
before the line is disconnected.
*/
static t_stat atcd_detach (UNIT *uptr)
@@ -1975,8 +1988,9 @@ return;
The channel service routine runs only when there are characters to read or
write. It is scheduled either at a realistic rate corresponding to the
programmed baud rate of the channel to be serviced, or at a somewhat faster
optimized rate. It is entered when a channel buffer is ready for output or
when the poll routine determines that there are characters ready for input.
optimized rate. It is entered when a channel buffer is ready for output,
when the poll routine determines that there are characters ready for input,
or while waiting for an ACK to complete an ENQ/ACK handshake.
On entry, the receive channel buffer is checked for a character. If one is
not already present, then the terminal multiplexer library is called to
@@ -1984,6 +1998,12 @@ return;
processed. If the receive channel has its "diagnose" bit set, the character
is also passed to the auxiliary channels.
If a received character is not available, then the unit's "wait" field is
checked to see if an ACK is expected in reply to an earlier ENQ. If a wait
time is present, it is doubled, and the service is rescheduled. However, if
the new wait time is longer than the current poll time, service rescheduling
is abandoned in favor of the normal poll for received characters.
The send channel buffer is then checked for a character to output. If one is
present, then if it is an all-mark (sync) character, it is discarded, as the
receiver would never see it. Otherwise, if the TDI is in diagnostic mode,
@@ -1998,18 +2018,36 @@ return;
simulation console (if output is to channel 0) or to the terminal multiplexer
library for output via Telnet or a serial port on the host machine. If the
channel has its "diagnose" bit set, the character is also passed to the
auxiliary channels.
auxiliary channels. If an ENQ was transmitted, service is rescheduled to
wait for reception of the ACK.
If the data flag is clear, the indicated receive and send channels are
checked for completion flags. If either is set, an interrupt is requested.
If characters remain in the Telnet receive buffer, the service routine is
rescheduled to receive the next one. Otherwise, the routine goes idle until
the next character is output or the next poll determines that there are
characters to receive.
Implementation notes:
1. Calling "tmxr_getc_ln" for channel 0 is OK, as reception is disabled by
1. The "wait" fields of the channel units are not used (i.e., are set to
zero) except when channels are waiting for ACKs. Because we want to
retrieve the ACK as quickly as possible but also minimize the load on the
host system, we initially wait the normal reception time (fast or
realistic) and then double the wait each time it expires without
reception. Therefore, a non-zero "wait" value indicates that an ACK is
expected.
2. Receipt of any character cancels a pending ACK wait, even though it is
possible that the character is not an ACK (for example, if the character
was received but not processed before the ENQ was sent).
3. Calling "tmxr_getc_ln" for channel 0 is OK, as reception is disabled by
default and therefore will return 0.
2. The send channel buffer will always be non-zero if a character is present
4. The send channel buffer will always be non-zero if a character is present
(even a NUL) because the data word will have DDS_IS_SEND set.
The receive buffer will always be non-zero if a character is present
@@ -2018,27 +2056,45 @@ return;
TMXR_VALID set, and characters looped back from sending will have
DDS_IS_SEND set.
3. Reception of a loopback character is performed immediately because the
5. Reception of a loopback character is performed immediately because the
reception occurs concurrently with transmission. Reception of a locally
generated ACK is scheduled with a one-character delay to reflect the
remote device transmission delay.
4. If storing an ACK locally overwrites a character already present but not
6. If storing an ACK locally overwrites a character already present but not
yet processed, then the receive routine will set the character lost flag.
5. Both TMXR_VALID and SCPE_KFLAG are set on internally generated ACKs only
7. Both TMXR_VALID and SCPE_KFLAG are set on internally generated ACKs only
so that a debug trace will record the generation correctly.
6. The console library "sim_putchar_s" routine and the terminal multiplexer
library "tmxr_putc_ln" routine return SCPE_STALL if the Telnet output
buffer is full. In this case, transmission is rescheduled with a delay
to allow the buffer to drain.
8. The console library "sim_putchar_s" routine and the terminal multiplexer
library "tmxr_putc_ln" routine return SCPE_STALL if they are called when
the transmit buffer is full. When called to add the last character to
the buffer, the routines return SCPE_OK but also change the "xmte" field
of the terminal multiplexer line (TMLN) structure from 1 to 0 to indicate
that further calls will be rejected; the value is set back to 1 when the
transmit buffer empties.
They also return SCPE_LOST if the line has been dropped on the remote
end. We ignore the error here to allow the simulation to continue while
ignoring the output.
Entry with the transmit buffer full causes the service to be rescheduled
to retry the write after a short delay. The "tmxr_poll_tx" routine must
be called in this case, as it is responsible for transmitting the buffer
contents and therefore freeing space in the buffer.
7. The receive/send completion flag (buffer flag) will not set unless the
Both library "put" routines also return SCPE_LOST if the line has been
dropped on the remote end. We ignore that error here to allow the
simulation to continue while ignoring the output to a disconnected
terminal.
9. Characters written using "tmxr_putc_ln" are buffered and not transmitted
until the buffer is full, the character is an ENQ (and so we will be
waiting to receive an ACK), or the next input poll is performed. The
last case ensures that the buffer is flushed when output is complete, as
there is no indication from the CPU that the last character has been
sent. This does incur a delay of up to 10 milliseconds, but this is
imperceptible by the user. Buffering offers significantly better
throughput compared to transmitting each character as it is written.
10. The receive/send completion flag (buffer flag) will not set unless the
interrupt enable flag for that channel is also set. If enable is not
set, the completion indication will be lost.
*/
@@ -2057,18 +2113,36 @@ dprintf (atcd_dev, DEB_SERV, "Channel %d service entered\n",
/* Reception service */
recv_data = recv_buffer [channel]; /* get the current buffer character */
recv_data = recv_buffer [channel]; /* get the current buffer character */
if (recv_data == 0) /* if there's none present */
recv_data = tmxr_getc_ln (&atcd_ldsc [channel]); /* then see if there's a character ready via Telnet */
if (recv_data == 0) { /* if no character is present */
if (uptr->wait) /* then if the channel is waiting for an ACK */
tmxr_poll_rx (&atcd_mdsc); /* then poll the line to see if it has arrived */
if (recv_data & ~DDR_DATA_MASK) { /* if we now have a valid character */
receive (channel, recv_data, loopback); /* then process the reception */
if (recv_param [channel] & DPI_DIAGNOSE) /* if a diagnosis is requested */
diagnose (recv_param [channel], recv_data); /* then route the data to the auxiliary channels */
recv_data = tmxr_getc_ln (&atcd_ldsc [channel]); /* see if there's now a character ready */
}
if (recv_data & ~DDR_DATA_MASK) { /* if we now have a valid character */
receive (channel, recv_data, loopback); /* then process the reception */
if (recv_param [channel] & DPI_DIAGNOSE) /* if a diagnosis is requested */
diagnose (recv_param [channel], recv_data); /* then route the data to the auxiliary channels */
uptr->wait = 0; /* clear any pending ACK wait */
}
else if (uptr->wait) { /* otherwise if an ACK is expected but has not arrived */
uptr->wait = uptr-> wait * 2; /* then double the wait time for the next check */
if (uptr->wait < poll_unit.wait) { /* if the wait is shorter than the standard poll wait */
sim_activate (uptr, uptr->wait); /* then reschedule the line service */
dprintf (atcd_dev, DEB_SERV, "Channel %d delay %d service rescheduled for ACK\n",
channel, uptr->wait);
}
}
/* Transmission service */
if (send_buffer [channel]) { /* if data is available to send */
@@ -2132,43 +2206,56 @@ if (send_buffer [channel]) { /* if data is availa
cvtd_data = sim_tt_outcvt (LOWER_BYTE (send_data), /* so convert it as directed */
TT_GET_MODE (uptr->flags)); /* by the output mode flag */
if (cvtd_data >= 0) /* if the converted character is printable */
if (channel == 0) /* then if we are writing to channel 0 */
result = sim_putchar_s (cvtd_data); /* then output it to the simulation console */
else /* otherwise */
result = tmxr_putc_ln (&atcd_ldsc [channel], /* output it to the multiplexer line */
cvtd_data);
if (result == SCPE_STALL) { /* if the buffer is full */
if (cvtd_data >= 0 && atcd_ldsc [channel].xmte == 0) { /* if it's printable but the transmit buffer is full */
activate_unit (uptr, Stall); /* then retry the output a while later */
result = SCPE_OK; /* and return OK to continue */
tmxr_poll_tx (&atcd_mdsc); /* transmit the line buffer */
dprintf (atcd_dev, DEB_XFER, "Channel %d character %s transmission stalled for full buffer\n",
channel, fmt_char (cvtd_data));
}
else if (result == SCPE_OK || result == SCPE_LOST) { /* otherwise if the character is queued to transmit */
tmxr_poll_tx (&atcd_mdsc); /* then send (or ignore) it */
else { /* otherwise the character will be consumed */
if (cvtd_data >= 0) /* if the converted character is printable */
if (channel == 0) /* then if we are writing to channel 0 */
result = sim_putchar_s (cvtd_data); /* then output it to the simulation console */
if (DPRINTING (atcd_dev, DEB_XFER))
if (result == SCPE_LOST)
hp_debug (&atcd_dev, DEB_XFER, "Channel %d character %s discarded by connection loss\n",
channel, fmt_char (char_data));
else { /* otherwise */
result = tmxr_putc_ln (&atcd_ldsc [channel], /* output it to the multiplexer line */
cvtd_data);
else if (cvtd_data >= 0)
hp_debug (&atcd_dev, DEB_XFER, "Channel %d character %s sent\n",
channel, fmt_char (cvtd_data));
if (char_data == ENQ /* if sending an ENQ */
|| atcd_ldsc [channel].xmte == 0) /* or the output buffer is full */
tmxr_poll_tx (&atcd_mdsc); /* then transmit the line buffer */
}
else
hp_debug (&atcd_dev, DEB_XFER, "Channel %d character %s discarded by output filter\n",
channel, fmt_char (char_data));
if (result == SCPE_OK || result == SCPE_LOST) { /* if the character is queued to transmit */
if (DPRINTING (atcd_dev, DEB_XFER))
if (result == SCPE_LOST)
hp_debug (&atcd_dev, DEB_XFER, "Channel %d character %s discarded by connection loss\n",
channel, fmt_char (char_data));
if (send_param [channel] & DPI_DIAGNOSE) /* if a diagnosis is requested */
diagnose (send_param [channel], send_data); /* then route the data to the auxiliary channels */
else if (cvtd_data >= 0)
hp_debug (&atcd_dev, DEB_XFER, "Channel %d character %s sent\n",
channel, fmt_char (cvtd_data));
send_buffer [channel] = 0; /* clear the buffer */
else
hp_debug (&atcd_dev, DEB_XFER, "Channel %d character %s discarded by output filter\n",
channel, fmt_char (char_data));
if (send_param [channel] & DPI_ENABLE_IRQ) /* if this channel is enabled to interrupt */
send_status [channel] |= DST_COMPLETE; /* then set the completion flag */
if (send_param [channel] & DPI_DIAGNOSE) /* if a diagnosis is requested */
diagnose (send_param [channel], send_data); /* then route the data to the auxiliary channels */
result = SCPE_OK; /* return OK in case the connection was lost */
send_buffer [channel] = 0; /* clear the buffer */
if (send_param [channel] & DPI_ENABLE_IRQ) /* if this channel is enabled to interrupt */
send_status [channel] |= DST_COMPLETE; /* then set the completion flag */
if (cvtd_data == ENQ && result == SCPE_OK) /* if an ENQ was successfully sent */
uptr->wait = activate_unit (uptr, Receive); /* then schedule the ACK reception */
result = SCPE_OK; /* return OK in case the connection was lost */
}
}
}
}
@@ -2177,6 +2264,9 @@ if (send_buffer [channel]) { /* if data is availa
if (tdi_data_flag == CLEAR) /* if an interrupt is not currently pending */
scan_channels (channel); /* then scan the channels for completion flags */
if (tmxr_rqln (&atcd_ldsc [channel])) /* if characters are still available on this channel */
activate_unit (uptr, Receive); /* then reschedule the line service */
return result; /* return the result of the service */
}
@@ -2184,10 +2274,9 @@ return result; /* return the result of
/* Multiplexer poll service.
The poll service routine is used to poll for Telnet connections and incoming
characters. It also polls the simulation console for channel 0. Polling
starts at simulator startup or when the TDI is enabled and stops when it is
disabled.
characters. It also polls the simulation console for channel 0 and flushes
the output buffers for all channels. Polling starts at simulator startup or
when the TDI is enabled and stops when it is disabled.
Implementation notes:
@@ -2200,20 +2289,30 @@ return result; /* return the result of
may be shorter than the channel service time, and as the console provides
no buffering, a second character received before the channel service had
been entered would be lost.
3. A channel that is waiting for an ACK to complete an ENQ/ACK handshake has
its unit "wait" field set non-zero. If the field value is greater than
the realistic reception time, then the line service is scheduled
immediately, as the channel has already waited the minimum time necessary
(the "wait" field value is doubled each time the line service is entered
before the ACK has been received). Otherwise, the service is scheduled
using the normal reception time.
*/
static t_stat poll_service (UNIT *uptr)
{
int32 chan, line_state;
int32 chan, line_state;
t_stat status = SCPE_OK;
dprintf (atcd_dev, DEB_PSERV, "Poll service entered\n");
dprintf (atcd_dev, DEB_PSERV, "Poll delay %d service entered\n",
uptr->wait);
if ((atcc_dev.flags & DEV_DIS) == 0)
dprintf (atcc_dev, DEB_PSERV, "Poll service entered\n");
dprintf (atcc_dev, DEB_PSERV, "Poll delay %d service entered\n",
uptr->wait);
if ((atcd_dev.flags & DEV_DIAG) == 0) { /* if we're not in diagnostic mode */
chan = tmxr_poll_conn (&atcd_mdsc); /* then check for a new multiplex connection */
chan = tmxr_poll_conn (&atcd_mdsc); /* then check for a new multiplexer connection */
if (chan != -1) { /* if a new connection was established */
atcd_ldsc [chan].rcve = TRUE; /* then enable the channel to receive */
@@ -2223,7 +2322,8 @@ if ((atcd_dev.flags & DEV_DIAG) == 0) { /* if we're not in diagn
}
}
tmxr_poll_rx (&atcd_mdsc); /* poll the multiplex connections for input */
tmxr_poll_tx (&atcd_mdsc); /* flush the multiplexer output buffers */
tmxr_poll_rx (&atcd_mdsc); /* and poll the multiplexer connections for input */
if ((atcc_dev.flags & (DEV_DIAG | DEV_DIS)) == 0) /* if we're not in diagnostic mode or are disabled */
for (chan = FIRST_TERM; chan <= LAST_TERM; chan++) /* then scan the channels for line state changes */
@@ -2257,9 +2357,15 @@ if (status >= SCPE_KFLAG) { /* if a character was pr
line_service (&line_unit [0]); /* run the system console's I/O service */
}
for (chan = FIRST_TERM; chan <= LAST_TERM; chan++) /* check each of the receive channels for available input */
if (tmxr_rqln (&atcd_ldsc [chan])) /* if characters are available on this channel */
activate_unit (&line_unit [chan], Receive); /* then activate the channel's I/O service */
for (chan = FIRST_TERM; chan <= LAST_TERM; chan++) /* check each of the channels for available input */
if (tmxr_rqln (&atcd_ldsc [chan])) /* if characters are available on this channel */
if (line_unit [chan].wait > line_unit [chan].recv_time) { /* then if the channel is waiting for an ACK */
sim_cancel (&line_unit [chan]); /* then cancel any current wait */
activate_unit (&line_unit [chan], Loop); /* and activate the line service immediately */
}
else /* otherwise this is a normal input */
activate_unit (&line_unit [chan], Receive); /* so schedule with the normal receive timing */
if (cpu_is_calibrated) /* if the process clock is calibrated */
uptr->wait = sim_activate_time (cpu_pclk_uptr); /* then synchronize with it */
@@ -2291,7 +2397,7 @@ return status; /* return the service st
called.
*/
static t_stat activate_unit (UNIT *uptr, ACTIVATOR reason)
static int32 activate_unit (UNIT *uptr, ACTIVATOR reason)
{
const int32 channel = (int32) (uptr - line_unit); /* the channel number */
int32 delay = 0;
@@ -2339,7 +2445,8 @@ else /* otherwise, we are in
dprintf (atcd_dev, DEB_SERV, "Channel %d delay %d service scheduled\n",
channel, delay);
return sim_activate (uptr, delay); /* activate the unit and return the activation status */
sim_activate (uptr, delay); /* activate the unit */
return delay; /* and return the activation delay */
}
@@ -2639,17 +2746,20 @@ else { /* otherwise a normal ch
recv_buffer [channel] = recv_data | pad; /* and replace the character in the buffer */
}
if (recv_param [channel] & DPI_ENABLE_ECHO) { /* if the channel has echo enabled */
char_echo = sim_tt_outcvt (recv_data, /* then convert the character per the output mode */
if (recv_param [channel] & DPI_ENABLE_ECHO) { /* if the channel has echo enabled */
char_echo = sim_tt_outcvt (recv_data, /* then convert the character per the output mode */
TT_GET_MODE (line_unit [channel].flags));
if (char_echo >= 0) { /* if the converted character is valid for the mode */
if (channel == 0) /* then if this is for channel 0 */
sim_putchar (char_echo); /* then write it back to the simulation console */
if (char_echo >= 0) { /* if the converted character is valid for the mode */
if (channel == 0) /* then if this is for channel 0 */
sim_putchar (char_echo); /* then write it back to the simulation console */
else { /* otherwise */
tmxr_putc_ln (&atcd_ldsc [channel], char_echo); /* write it to the multiplexer output line */
tmxr_poll_tx (&atcd_mdsc); /* and poll to transmit it now */
else { /* otherwise */
tmxr_putc_ln (&atcd_ldsc [channel], /* write it to the multiplexer output line */
char_echo);
if (atcd_ldsc [channel].xmte == 0) /* if the output buffer is full */
tmxr_poll_tx (&atcd_mdsc); /* then transmit the line buffer */
}
dprintf (atcd_dev, DEB_XFER, ("Channel %d character %s echoed\n"),

View File

@@ -25,6 +25,8 @@
CPU HP 3000 Series III Central Processing Unit
05-Sep-17 JDB Removed the -B (binary display) option; use -2 instead
Changed REG_A (permit any symbolic override) to REG_X
19-Jan-17 JDB Added comments describing the OPND and EXEC trace options
29_Dec-16 JDB Changed the status mnemonic flag from REG_S to REG_T
07-Nov-16 JDB Renamed cpu_byte_to_word_ea to cpu_byte_ea
@@ -1024,8 +1026,7 @@ UNIT cpu_unit [] = {
modification. User flags describe the permitted and default display formats,
as follows:
- REG_A permits any display
- REG_B permits binary display
- REG_X permits any symbolic display
- REG_M defaults to CPU instruction mnemonic display
- REG_T defaults to CPU status mnemonic display
@@ -1058,15 +1059,15 @@ static REG cpu_reg [] = {
{ ORDATA (SR, SR, 3), REG_FIT }, /* stack register counter */
{ ORDATA (Z, Z, 16), REG_FIT }, /* stack limit register */
{ ORDATA (SBANK, SBANK, 4), REG_FIT }, /* stack segment bank register */
{ ORDATA (RA, TR [0], 16), REG_A | REG_FIT }, /* top of stack register */
{ ORDATA (RB, TR [1], 16), REG_A | REG_FIT }, /* top of stack - 1 register */
{ ORDATA (RC, TR [2], 16), REG_A | REG_FIT }, /* top of stack - 2 register */
{ ORDATA (RD, TR [3], 16), REG_A | REG_FIT }, /* top of stack - 3 register */
{ ORDATA (X, X, 16), REG_A | REG_FIT }, /* index register */
{ ORDATA (STA, STA, 16), REG_T | REG_B | REG_FIT }, /* status register */
{ ORDATA (SWCH, SWCH, 16), REG_A | REG_FIT }, /* switch register */
{ ORDATA (CPX1, CPX1, 16), REG_B | REG_FIT }, /* run-mode interrupt flags */
{ ORDATA (CPX2, CPX2, 16), REG_B | REG_FIT }, /* halt-mode interrupt flags */
{ ORDATA (RA, TR [0], 16), REG_X | REG_FIT }, /* top of stack register */
{ ORDATA (RB, TR [1], 16), REG_X | REG_FIT }, /* top of stack - 1 register */
{ ORDATA (RC, TR [2], 16), REG_X | REG_FIT }, /* top of stack - 2 register */
{ ORDATA (RD, TR [3], 16), REG_X | REG_FIT }, /* top of stack - 3 register */
{ ORDATA (X, X, 16), REG_X | REG_FIT }, /* index register */
{ ORDATA (STA, STA, 16), REG_T | REG_FIT }, /* status register */
{ ORDATA (SWCH, SWCH, 16), REG_X | REG_FIT }, /* switch register */
{ ORDATA (CPX1, CPX1, 16), REG_FIT }, /* run-mode interrupt flags */
{ ORDATA (CPX2, CPX2, 16), REG_FIT }, /* halt-mode interrupt flags */
{ ORDATA (PCLK, PCLK, 16), REG_FIT }, /* process clock register */
{ ORDATA (CNTR, CNTR, 6), REG_HRO | REG_FIT }, /* microcode counter */
{ ORDATA (MOD, MOD, 16), REG_HRO | REG_FIT }, /* module control register */
@@ -1331,8 +1332,8 @@ DEVICE cpu_dev = {
volatile-qualified type and have been changed between the setjmp
invocation and longjmp call are indeterminate."
Therefore, after a microcode abort, we cannot depend upon the values of
any local variables.
Therefore, the "device" and "status" variables are marked volatile to
ensure that they are reloaded after a longjmp caused by a micrcode abort.
2. In hardware, the NEXT microcode order present at the end of each
instruction transfers the NIR content to the CIR, reads the memory word
@@ -1398,10 +1399,11 @@ static const char *const stack_formats [] = { /* stack register displa
};
int abortval;
HP_WORD label, parameter, device;
HP_WORD label, parameter;
TRAP_CLASS trap;
t_bool exec_test;
t_stat status = SCPE_OK;
volatile HP_WORD device;
volatile t_stat status = SCPE_OK;
/* Instruction prelude */

View File

@@ -1,6 +1,6 @@
/* hp3000_defs.h: HP 3000 simulator general declarations
Copyright (c) 2016, J. David Bryan
Copyright (c) 2016-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
@@ -23,7 +23,8 @@
in advertising or otherwise to promote the sale, use or other dealings in
this Software without prior written authorization from the author.
29_Dec-16 JDB Changed the status mnemonic flag from REG_S to REG_T
16-Oct-17 JDB Suppressed logical-not-parentheses warning on clang
29-Dec-16 JDB Changed the status mnemonic flag from REG_S to REG_T
20-Nov-16 JDB Added mapped memory access classes
24-Oct-16 JDB Added half-byte definitions for CIS decoding
10-Oct-16 JDB Moved ACCESS_CLASS definition here from hp3000_cpu.h
@@ -134,6 +135,7 @@
*/
#if defined (__clang__)
#pragma clang diagnostic ignored "-Wlogical-not-parentheses"
#pragma clang diagnostic ignored "-Wlogical-op-parentheses"
#pragma clang diagnostic ignored "-Wbitwise-op-parentheses"
#pragma clang diagnostic ignored "-Wshift-op-parentheses"
@@ -147,10 +149,12 @@
/* Device register display mode flags */
#define REG_A (1u << REG_V_UF + 0) /* permit any display */
#define REG_B (1u << REG_V_UF + 1) /* permit binary display */
#define REG_M (1u << REG_V_UF + 2) /* default to instruction mnemonic display */
#define REG_T (1u << REG_V_UF + 3) /* default to status mnemonic display */
#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) */
#define REG_T (1u << REG_V_UF + 3) /* default format is -T (status mnemonic) */
/* Register macros.

View File

@@ -1,6 +1,6 @@
/* hp3000_ds.c: HP 3000 30229B Cartridge Disc Interface simulator
Copyright (c) 2016, J. David Bryan
Copyright (c) 2016-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
@@ -25,6 +25,7 @@
DS HP 30229B Cartridge Disc Interface
05-Sep-17 JDB Changed REG_A (permit any symbolic override) to REG_X
12-Sep-16 JDB Changed DIB register macro usage from SRDATA to DIB_REG
09-Jun-16 JDB Added casts for ptrdiff_t to int32 values
08-Jun-16 JDB Corrected %d format to %u for unsigned values
@@ -435,7 +436,7 @@ static REG ds_reg [] = {
{ FLDATA (OVRUN, flags, 5) },
{ FLDATA (XFRNG, flags, 6) },
{ ORDATA (BUFFER, buffer_word, 16), REG_A | REG_FIT | PV_RZRO },
{ ORDATA (BUFFER, buffer_word, 16), REG_X | REG_FIT | PV_RZRO },
{ ORDATA (STATUS, status_word, 16), REG_FIT | PV_RZRO },
{ DRDATA (RETRY, retry_counter, 4), REG_FIT | PV_LEFT },

View File

@@ -321,15 +321,15 @@ struct dib { /* the Device Information Block
};
#define DIB_REGS(dib) \
/* Macro Name Location Width Flags */ \
/* ------ ------- -------------------------- ----- ------- */ \
{ DRDATA (DIBDN, dib.device_number, 32), REG_HRO }, \
{ DRDATA (DIBSRN, dib.service_request_number, 32), REG_HRO }, \
{ DRDATA (DIBPRI, dib.interrupt_priority, 32), REG_HRO }, \
{ ORDATA (DIBMASK, dib.interrupt_mask, 32), REG_HRO }, \
{ ORDATA (DIBIRQ, dib.interrupt_request, 32), REG_HRO }, \
{ ORDATA (DIBACT, dib.interrupt_active, 32), REG_HRO }, \
{ ORDATA (DIBSR, dib.service_request, 32), REG_HRO }
/* Macro Name Location Width Flags */ \
/* ------ ------- -------------------------- ----- ------- */ \
{ DRDATA (DIBDN, dib.device_number, 32), REG_HRO }, \
{ DRDATA (DIBSRN, dib.service_request_number, 32), REG_HRO }, \
{ DRDATA (DIBPRI, dib.interrupt_priority, 32), REG_HRO }, \
{ ORDATA (DIBMASK, dib.interrupt_mask, 32), REG_HRO }, \
{ ORDATA (DIBIRQ, dib.interrupt_request, 32), REG_HRO }, \
{ ORDATA (DIBACT, dib.interrupt_active, 32), REG_HRO }, \
{ ORDATA (DIBSR, dib.service_request, 32), REG_HRO }
/* Calibrated timer numbers */

View File

@@ -25,6 +25,12 @@
LP HP 30209A Line Printer Interface
07-Sep-17 JDB Changed PCHR and UPCHR registers to PUNCHR and UNPCHR
Changed PRTBUF, OVPCHR, PUNCHR, and UNPCHR to REG_A
05-Sep-17 JDB Changed REG_A (permit any symbolic override) to REG_X
20-Jul-17 JDB Added a forced detach option (-F switch) to "lp_detach"
24-Jun-17 JDB Added "report_error", fixed "lp_set_model" times bug
22-Jun-17 JDB Moved deferred offline/detach cancel to SET ONLINE
26-Apr-17 JDB Fixed "lp_service" return for VFU channel not punched
Restricted auto-print on buffer full to the 2607
Paper fault is now delayed until the TOF for the 2607
@@ -205,19 +211,17 @@
issued while the print buffer contains data or the printer unit is busy
executing a print action.
The SET LP OFFLINE and SET LP DETACH commands check for data in the print
buffer or a print operation in progress. If either condition is true, they
set their respective deferred-action flags and display "Command deferred." A
SHOW LP will show that the device is still online and attached. Once
The SET LP OFFLINE and DETACH LP commands check for data in the print buffer
or a print operation in progress. If either condition is true, they set
their respective deferred-action flags and display "Command not completed."
A SHOW LP will show that the device is still online and attached. Once
simulation is resumed and the print operation completes, the printer is set
offline or detached as requested. No console message reports this, as it is
assumed that the executing program will detect the condition and report
accordingly. A subsequent SHOW LP will indicate the new status.
A SET LP ONLINE or ATTACH LP command when the corresponding deferred-action
flag is set simply clears the flag. In particular, an ATTACH LP command must
not specify a new image filename; if one is specified while a deferred detach
is in progress, the routine returns SCPE_NOFNC ("Command not allowed").
A SET LP ONLINE command when a deferred-action flag is set simply clears the
flag, which cancels the pending offline or detach condition.
A RESET LP command also clears the deferred-action flags and so clears any
pending offline or detach. However, it also clears the print buffer and
@@ -480,11 +484,22 @@
#define DEV_REALTIME (1u << DEV_REALTIME_SHIFT) /* realistic timing flag */
/* Printer unit flags */
/* Printer unit flags.
#define UNIT_MODEL_SHIFT (UNIT_V_UF + 0) /* bits 0-2: printer model ID */
#define UNIT_EXPAND_SHIFT (UNIT_V_UF + 3) /* bits 3-3: printer uses expanded output */
#define UNIT_OFFLINE_SHIFT (UNIT_V_UF + 4) /* bits 4-4: printer is offline */
UNIT_V_UF + 7 6 5 4 3 2 1 0
+---+---+---+---+---+---+---+---+
| - | - | - | O | E | model |
+---+---+---+---+---+---+---+---+
Where:
O = offline
E = expanded output
*/
#define UNIT_MODEL_SHIFT (UNIT_V_UF + 0) /* printer model ID */
#define UNIT_EXPAND_SHIFT (UNIT_V_UF + 3) /* printer uses expanded output */
#define UNIT_OFFLINE_SHIFT (UNIT_V_UF + 4) /* printer is offline */
#define UNIT_MODEL_MASK 0000007u /* model ID mask */
@@ -541,10 +556,10 @@ typedef enum {
This table contains the characteristics that vary between printer models.
The "char_set" field values reflect printer Option 001, 96/128-character set.
The "not_ready" field indicates whether a paper fault sets not-ready status
or simply takes the printer offline. The "fault_at_eol" field indicates
whether a paper fault is reported at the end of any line (TRUE) or only at
the top of the next form (FALSE).
The "not_ready" field indicates whether a paper fault sets a separate
not-ready status or simply takes the printer offline. The "fault_at_eol"
field indicates whether a paper fault is reported at the end of any line or
only at the top of the next form.
*/
typedef struct {
@@ -579,9 +594,10 @@ static const PRINTER_PROPS print_props [] = { /* printer properties, indexed b
Implementation notes:
1. Although all of the printers operate more slowly with a 96/128-character
set than with a 64-character set, the times reflect the smaller set size.
Also, some models provide different print rates, depending on how many
and/or which characters are printed. These variances are not simulated.
set installed than with a 64-character set, the times reflect the smaller
set size. Also, some models provide different print rates, depending on
how many and/or which characters are printed. These variations are not
simulated.
*/
typedef struct {
@@ -1046,7 +1062,7 @@ static t_bool power_warning = FALSE; /* PFWARN is not asserted to the
/* Printer state */
static t_bool paper_fault = TRUE; /* TRUE if the printer is out of paper */
static t_bool tape_fault = FALSE; /* TRUE if there is no punch in a VFU channel command */
static t_bool tape_fault = FALSE; /* TRUE if there is no punch in a commanded VFU channel */
static t_bool offline_pending = FALSE; /* TRUE if an offline request is waiting for the printer to finish */
static uint32 overprint_char = DEL; /* character to use if overprinted */
static uint32 current_line = 1; /* current form line */
@@ -1077,6 +1093,7 @@ static t_stat ui_reset (DEVICE *dptr);
static t_stat master_reset (t_bool programmed_clear);
static void clear_interface_logic (void);
static void activate_unit (UNIT *uptr);
static void report_error (FILE *stream);
static OUTBOUND_SET set_interrupt (uint32 interrupt);
static OUTBOUND_SET set_device_status (uint32 status_mask, uint32 new_status_word);
static OUTBOUND_SET handshake_xfer (void);
@@ -1177,12 +1194,12 @@ static REG lp_reg [] = {
{ ORDATA (CNTL, control_word, 16), PV_RZRO },
{ ORDATA (ISTAT, int_status_word, 16), PV_RZRO },
{ ORDATA (DSTAT, dev_status_word, 16), PV_RZRO },
{ ORDATA (READ, read_word, 16), PV_RZRO | REG_A },
{ ORDATA (WRITE, write_word, 16), PV_RZRO | REG_A },
{ ORDATA (READ, read_word, 16), PV_RZRO | REG_X },
{ ORDATA (WRITE, write_word, 16), PV_RZRO | REG_X },
{ YRDATA (J2WX, jumper_set, 10, PV_RZRO) },
{ ORDATA (DATOUT, data_out, 16), PV_RZRO | REG_A },
{ ORDATA (DATIN, data_in, 16), PV_RZRO | REG_A },
{ ORDATA (DATOUT, data_out, 16), PV_RZRO | REG_X },
{ ORDATA (DATIN, data_in, 16), PV_RZRO | REG_X },
{ FLDATA (DCOUT, device_command_out, 0) },
{ FLDATA (DFIN, device_flag_in, 0) },
@@ -1206,8 +1223,8 @@ static REG lp_reg [] = {
{ DRDATA (FORMLN, form_length, 8), PV_LEFT | REG_RO },
{ BRDATA (TITLE, vfu_title, 8, 8, LINE_SIZE), REG_HRO },
{ BRDATA (VFU, VFU, 2, VFU_WIDTH, VFU_SIZE), PV_RZRO | REG_RO },
{ ORDATA (PCHR, punched_char, 8), PV_RZRO | REG_A },
{ ORDATA (UPCHR, unpunched_char, 8), PV_RZRO | REG_A },
{ ORDATA (PUNCHR, punched_char, 8), PV_RZRO | REG_A },
{ ORDATA (UNPCHR, unpunched_char, 8), PV_RZRO | REG_A },
{ DRDATA (BTIME, fast_times.buffer_load, 24), PV_LEFT | REG_NZ },
{ DRDATA (PTIME, fast_times.print, 24), PV_LEFT | REG_NZ },
@@ -1795,7 +1812,7 @@ return SCPE_OK; /* return success */
Implementation notes:
1. Calling "master_clear" with a FALSE parameter indicates that this is a
1. Calling "master_reset" with a FALSE parameter indicates that this is a
commanded reset. This allows the connected device-specific reset
routines to distinguish from a Programmed Master Clear.
*/
@@ -1911,6 +1928,23 @@ return;
}
/* Report a stream I/O error to the console.
If a stream I/O error has been detected, this routine will print an error
message to the simulation console and clear the stream's error indicator.
*/
static void report_error (FILE *stream)
{
cprintf ("%s simulator printer I/O error: %s\n", /* report the error to the console */
sim_name, strerror (errno));
clearerr (stream); /* clear the error */
return;
}
/* Set an interrupt.
The interrupt bit specified is set in the interrupt status word. If enabled,
@@ -2491,11 +2525,12 @@ return outbound_signals; /* return INTREQ if any
conclude the handshake.
Control word bit 10 determines whether the code on the data out lines is
interpreted as a character (0) or a format command (1). Character data is
loaded into the buffer; if the line length is exceeded, the printer
automatically prints the buffer contents, advances the paper one line, and
stores the new character in the empty buffer. If a control character is sent
but the printer cannot print it, a space is loaded in its place.
interpreted as a character (0) or a format command (1). If there is room in
the print buffer, the character is loaded. If not, then depending on the
model, the printer either discards the character or automatically prints the
buffer contents, advances the paper one line, and stores the new character in
the empty buffer. If a control character is sent but the printer cannot
print it, a space is loaded in its place.
A format command causes the current buffer to be printed, and then the paper
is advanced by a prescribed amount. Two output modes are provided: compact
@@ -2545,14 +2580,18 @@ return outbound_signals; /* return INTREQ if any
Implementation notes:
1. Because attached files are opened in binary mode, newline translation
1. When a paper-out condition is detected, the 2607 printer goes offline
only when the next top-of-form is reached. The 2613/17/18 printers go
offline as soon as the current line completes.
2. Because attached files are opened in binary mode, newline translation
(i.e., from LF to CR LF) is not performed by the host system. Therefore,
we write explicit CR LF pairs to end lines, even in compact mode, as
required for fidelity to HP peripherals. If bare LFs are used by the
host system, the printer output file must be postprocessed to remove the
CRs.
2. Overprinting in expanded mode is simulated by merging the lines in the
3. Overprinting in expanded mode is simulated by merging the lines in the
buffer. A format command to suppress spacing resets the buffer index but
saves the previous buffer length as a "high water mark" that will be
extended if the overlaying line is longer. This process may be repeated
@@ -2565,25 +2604,31 @@ return outbound_signals; /* return INTREQ if any
"overprint character" (which defaults to DEL, but can be changed by the
user) replaces the character in the buffer.
3. Printers that support 12-channel VFUs treat the VFU format command as
4. Printers that support 12-channel VFUs treat the VFU format command as
modulo 16. Printers that support 8-channel VFUs treat the command as
modulo 8.
4. As a convenience to the user, the printer output file is flushed when a
TOF operation is performed.
5. As a convenience to the user, the printer output file is flushed when a
TOF operation is performed. This permits inspection of the output file
from the SCP command prompt while output is ongoing.
5. The user may examine the TFAULT and PFAULT registers to determine why the
6. The user may examine the TFAULT and PFAULT registers to determine why the
printer went offline.
6. The transfer service may be called with a null pointer to update the
7. The transfer service may be called with a null pointer to update the
potential change in the flag state.
7. If printing is attempted with the printer offline, this routine will be
8. If printing is attempted with the printer offline, this routine will be
called with STROBE asserted (device_command_in TRUE) and DEMAND denied
(device_flag_in TRUE). The printer ignores STROBE if DEMAND is not
asserted, so we simply return in this case. This will hang the handshake
until the printer is set online, and we are reentered with DEMAND
asserted.
asserted. As a consequence, explicit protection against "uptr->fileref"
being NULL is not required.
9. Explicit tests for lowercase and control characters are much faster and
are used rather than calls to "islower" and "iscntrl", which must
consider the current locale.
*/
static t_stat lp_service (UNIT *uptr)
@@ -2828,14 +2873,11 @@ else if (device_flag_in == FALSE) { /* otherwise if STROBE h
slew_count, (slew_count == 1 ? "" : "s"), current_line);
}
if (ferror (uptr->fileref)) { /* if a host file system error occurred */
cprintf ("%s simulator printer I/O error: %s\n", /* then report the error to the console */
sim_name, strerror (errno));
if (ferror (uptr->fileref)) { /* if a host file system error occurred */
report_error (uptr->fileref); /* then report the error to the console */
clearerr (uptr->fileref); /* clear the error */
lp_set_alarm (uptr); /* set an alarm condition */
return SCPE_IOERR; /* and stop the simulator */
lp_set_alarm (uptr); /* set an alarm condition */
return SCPE_IOERR; /* and stop the simulator */
}
}
@@ -2849,7 +2891,7 @@ return SCPE_OK; /* return event service
equivalent of loading paper into the printer and pressing the ONLINE button.
The transition from offline to online causes an interrupt.
A new image file may be requested by giving the "-N" switch to the attach
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
@@ -2869,7 +2911,7 @@ return SCPE_OK; /* return event service
static t_stat lp_attach (UNIT *uptr, CONST char *cptr)
{
t_stat result = SCPE_OK;
t_stat result;
result = attach_unit (uptr, cptr); /* attach the specified printer image file */
@@ -2879,15 +2921,20 @@ if (result == SCPE_OK /* if the attach was suc
current_line = 1; /* reset the line counter to the top of the form */
if (sim_switches & SWMASK ('N')) /* if a new (empty) file was requested */
uptr->pos = 0; /* then position at the start of the file */
else if (fseek (uptr->fileref, 0, SEEK_END) == 0) /* otherwise append by seeking to the end of the file */
if (fseek (uptr->fileref, 0, SEEK_END) == 0) { /* append by seeking to the end of the file */
uptr->pos = (t_addr) ftell (uptr->fileref); /* and repositioning if the seek succeeded */
dprintf (lp_dev, DEB_CMD, "Printer paper loaded\n");
dprintf (lp_dev, DEB_CMD, "Printer paper loaded\n");
lp_set_locality (uptr, Online); /* set the printer online */
lp_set_locality (uptr, Online); /* set the printer online */
}
else { /* otherwise a host file system error occurred */
report_error (uptr->fileref); /* so report the error to the console */
lp_set_alarm (uptr); /* set an alarm condition */
result = SCPE_IOERR; /* and report that the attached failed */
}
}
paper_fault = FALSE; /* clear any existing paper fault */
@@ -2904,10 +2951,10 @@ return result; /* return the result of
/* Detach the printer image file.
The specified file is detached from the indicated unit. This is the
simulation equivalent to unloading the paper from the printer or the printer
running out of paper. The out-of-paper condition cause a paper fault alarm,
and the printer goes offline. The transition from online to offline causes
an interrupt.
simulation equivalent of running out of paper or unloading the paper from the
printer. The out-of-paper condition cause a paper fault alarm, and the
printer goes offline. The transition from online to offline causes an
interrupt.
When the printer runs out of paper, it will not go offline until characters
present in the buffer are printed and paper motion stops. In addition, the
@@ -2916,7 +2963,10 @@ return result; /* return the result of
In simulation, entering a DETACH LP command while the printer is busy will
defer the file detach until print operations reach the top of the next form
(2607) or until the current print operation completes (2613/17/18).
(2607) or until the current print operation completes (2613/17/18). An
immediate detach may be forced by adding the -F switch to the DETACH command.
This simulates physically removing the paper from the printer and succeeds
regardless of the current printer state.
Implementation notes:
@@ -2943,25 +2993,32 @@ if (uptr->flags & UNIT_ATTABLE) /* if we're being called
if ((uptr->flags & UNIT_ATT) == 0) /* then if the unit is not currently attached */
return SCPE_UNATT; /* then report it */
else if ((print_props [model].fault_at_eol /* otherwise if the printer faults at the end of any line */
|| current_line == 1) /* or the printer is at the top of the form */
&& lp_set_alarm (uptr) /* and a paper alarm is accepted */
|| (sim_switches & SIM_SW_SHUT)) { /* or this is a shutdown call */
paper_fault = TRUE; /* then set the out-of-paper condition */
else {
if (sim_switches & (SWMASK ('F') | SIM_SW_SHUT)) { /* if this is a forced detach or shut down request */
current_line = 1; /* then reset the printer to TOF to enable detaching */
sim_cancel (uptr); /* and terminate */
device_command_out = FALSE; /* any print action in progress */
}
dprintf (lp_dev, DEB_CMD, "Printer is out of paper\n");
if ((print_props [model].fault_at_eol /* otherwise if the printer faults at the end of any line */
|| current_line == 1) /* or the printer is at the top of the form */
&& lp_set_alarm (uptr)) { /* and a paper alarm is accepted */
paper_fault = TRUE; /* then set the out-of-paper condition */
return detach_unit (uptr); /* and detach the unit */
}
dprintf (lp_dev, DEB_CMD, "Printer is out of paper\n");
else { /* otherwise the alarm was rejected at this time */
paper_fault = TRUE; /* so set the out-of-paper condition */
offline_pending = TRUE; /* but defer the detach */
return detach_unit (uptr); /* and detach the unit */
}
dprintf (lp_dev, DEB_CMD, "Paper out request deferred until print completes\n");
else { /* otherwise the alarm was rejected at this time */
paper_fault = TRUE; /* so set the out-of-paper condition */
offline_pending = TRUE; /* but defer the detach */
cputs ("Command deferred\n"); /* but the actual detach must be deferred */
return SCPE_OK; /* until the buffer prints */
dprintf (lp_dev, DEB_CMD, "Paper out request deferred until print completes\n");
cprintf ("%s\n", sim_error_text (SCPE_INCOMP)); /* report that the actual detach must be deferred */
return SCPE_OK; /* until the buffer has been printed */
}
}
else /* otherwise */
@@ -3018,7 +3075,7 @@ switch ((DEVICE_MODES) value) { /* dispatch the mode to
break;
}
return SCPE_OK; /* the mode change succeeds */
return SCPE_OK; /* mode changes always succeed */
}
@@ -3033,7 +3090,7 @@ return SCPE_OK; /* the mode change succe
static t_stat lp_set_model (UNIT *uptr, int32 value, CONST char *cptr, void *desc)
{
if (lp_dev.flags & DEV_REALTIME) /* if the printer is in real-time mode */
dlyptr = &real_times [GET_MODEL (uptr->flags)]; /* then use the times for the new model */
dlyptr = &real_times [GET_MODEL (value)]; /* then use the times for the new model */
return SCPE_OK; /* allow the reassignment to proceed */
}
@@ -3044,26 +3101,29 @@ return SCPE_OK; /* allow the reassignmen
This validation routine is called to set the printer online or offline. The
"value" parameter is UNIT_OFFLINE if the printer is going offline and is zero
if the printer is going online. This simulates pressing the ON/OFFLINE
button on the printer.
button on the printer. The unit must be attached (i.e., paper must be
loaded), before the printer may be set online or offline.
If the printer is being taken offline, the buffer is checked to see if any
characters are present. If they are, or if the printer unit is currently
scheduled (i.e., executing a print operation), the offline request is
deferred until printing completes, and the routine prints "Command deferred"
to inform the user. Otherwise, the unit is set offline, DEMAND is denied,
and DEV END is asserted to indicate that the printer is not ready.
//
As a special case, a detach (out-of-paper condition) that has been deferred
until printing completes may be cancelled by setting the printer online.
deferred until printing completes, and the routine returns "Command not
complete" status to inform the user. Otherwise, the unit is set offline,
DEMAND is denied, and DEV END is asserted to indicate that the printer is not
ready.
If the printer is being put online, the unit must be attached (i.e., paper
must be loaded), or the command is rejected. If paper is present, the unit
is set online, and any tape fault present is cleared. If the sequencer
If the printer is being put online and paper is present, the unit is set
online, and any paper or tape fault present is cleared. If the sequencer
indicates an incomplete handshake, as would occur if paper ran out while
printing, the transfer service is called to complete the handshake by
asserting DEMAND. Otherwise, DEMAND is asserted explicitly, and DEV END is
denied.
As a special case, a detach (out-of-paper condition) or offline request that
has been deferred until printing completes may be cancelled by setting the
printer online. No other action is taken, because the printer has never
transitioned to the offline state.
Transitions between the offline and online state cause interrupts, and INTREQ
is asserted to the IOP if a transition occurred (but not, e.g., for a SET LP
OFFLINE command where the printer is already offline).
@@ -3071,9 +3131,9 @@ return SCPE_OK; /* allow the reassignmen
Implementation notes:
1. Because a deferred offline request is not fatal, we return SCPE_OK to
allow command files to continue to execute, but we print a warning to the
user.
1. Although a deferred offline request is not fatal, we return SCPE_INCOMP
to prevent "set_cmd" from setting the UNIT_OFFLINE bit in the unit flags
before the printer actually goes offline.
*/
static t_stat lp_set_on_offline (UNIT *uptr, int32 value, CONST char *cptr, void *desc)
@@ -3091,8 +3151,8 @@ else if (value == UNIT_ONLINE) /* otherwise if this is
lp_set_locality (uptr, Online); /* so set the printer online */
else if (lp_set_locality (uptr, Offline) == FALSE) { /* otherwise if it cannot be set offline now */
cputs ("Command deferred\n"); /* then let the user know */
dprintf (lp_dev, DEB_CMD, "Offline request deferred until print completes\n");
return SCPE_INCOMP; /* then let the user know */
}
return SCPE_OK; /* return operation success */
@@ -3189,8 +3249,8 @@ static t_stat lp_show_vfu (FILE *st, UNIT *uptr, int32 value, CONST void *desc)
static const char header_1 [] = " Ch 1 Ch 2 Ch 3 Ch 4 Ch 5 Ch 6 Ch 7 Ch 8 Ch 9 Ch10 Ch11 Ch12";
static const char header_2 [] = " ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----";
const PRINTER_TYPE model = GET_MODEL (uptr->flags);
const uint32 channel_count = print_props [model].vfu_channels;
const PRINTER_TYPE model = GET_MODEL (uptr->flags); /* the printer model number */
const uint32 channel_count = print_props [model].vfu_channels; /* the count of VFU channels */
uint32 chan, line, current_channel;
if (value == 0) /* if we're called for a summary display */
@@ -3328,8 +3388,8 @@ return NO_SIGNALS; /* no special control ac
This routine is called when an alarm condition exists. An alarm occurs when
paper is out (paper fault) or a VFU command addresses a channel that does not
contain a punch (tape fault). In response, the printer goes not ready and
offline.
contain a punch (tape fault). In response, the printer goes offline and,
for all models except the 2607, becomes not-ready.
On entry, the routine attempts to set the printer offline. If this succeeds,
the printer is set not-ready. If it fails (for reasons explained in the
@@ -3430,9 +3490,8 @@ dprintf (lp_dev, DEB_CMD, "Printer set %s\n",
if (signals & INTREQ) /* if the transition caused an interrupt */
iop_assert_INTREQ (&lp_dib); /* then assert the INTREQ signal */
offline_pending = FALSE;
return TRUE;
offline_pending = FALSE; /* the operation completed */
return TRUE; /* successfully */
}
@@ -3442,8 +3501,8 @@ return TRUE;
associated with the stream "vf" or with the standard 66-line tape if the
stream is NULL. The "uptr" parameter points to the printer unit.
The standard VFU tape (1535-2655 for the 8-channel HP 2607 and 2613-80001 for
the 12-channel HP 2613, 2617, and 2618) defines the channels as:
The standard VFU tape (02607-80024 for the 8-channel HP 2607 and 02613-80001
for the 12-channel HP 2613, 2617, and 2618) defines the channels as:
Chan Description
---- --------------
@@ -3457,12 +3516,12 @@ return TRUE;
8 Sixth page
9 Bottom of form
...with channels 10-12 uncommitted. A custom tape must dedicate channel 1 to
the top-of-form, but the other channels may be defined as desired.
...with channels 10-12 uncommitted.
A custom tape file starts with a VFU definition line and then contains one
channel-definition line for each line of the form. The number of lines
establishes the form length.
establishes the form length. Channel 1 must be dedicated to the top-of-form,
but the other channels may be defined as desired.
A semicolon appearing anywhere on a line begins a comment, and the semicolon
and all following characters are ignored. Zero-length lines, including lines
@@ -3542,7 +3601,7 @@ return TRUE;
static t_stat lp_load_vfu (UNIT *uptr, FILE *vf)
{
const PRINTER_TYPE model = GET_MODEL (uptr->flags); /* get the printer type */
const PRINTER_TYPE model = GET_MODEL (uptr->flags); /* the printer model number */
uint32 line, channel, vfu_status;
int32 len;
char buffer [LINE_SIZE], punch [LINE_SIZE], no_punch;
@@ -3550,10 +3609,8 @@ char *bptr, *tptr;
uint16 tape [VFU_SIZE] = { 0 };
if (vf == NULL) { /* if the standard VFU is requested */
strcpy (vfu_title, "Standard VFU"); /* then set the title */
tape [ 1] = VFU_CHANNEL_1; /* punch channel 1 for the top of form */
tape [60] = VFU_CHANNEL_2 | VFU_CHANNEL_9; /* punch channels 2 and 9 for the bottom of form */
tape [ 1] = VFU_CHANNEL_1; /* then punch channel 1 for the top of form */
tape [60] = VFU_CHANNEL_2 | VFU_CHANNEL_9; /* and channels 2 and 9 for the bottom of form */
for (line = 1; line <= 60; line++) { /* load each of the 60 printable lines */
tape [line] |= VFU_CHANNEL_3 /* punch channel 3 for single space */
@@ -3567,6 +3624,7 @@ if (vf == NULL) { /* if the standard VFU i
}
form_length = 66; /* set the form length */
strcpy (vfu_title, "Standard VFU"); /* and set the title */
}
else { /* otherwise load a custom VFU from the file */
@@ -3690,12 +3748,9 @@ while (len == 0) {
if (feof (vf)) /* then if the end of file was seen */
return 0; /* then return an EOF indication */
else { /* otherwise report the error to the console */
cprintf ("%s simulator line printer I/O error: %s\n",
sim_name, strerror (errno));
clearerr (vf); /* clear the error */
return -1; /* and return an error indication */
else { /* otherwise */
report_error (vf); /* report the error to the console */
return -1; /* and return an error indication */
}
len = strlen (line); /* get the current line length */

View File

@@ -1,6 +1,6 @@
/* hp3000_ms.c: HP 3000 30215A Magnetic Tape Controller Interface simulator
Copyright (c) 2016, J. David Bryan
Copyright (c) 2016-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
@@ -25,6 +25,7 @@
MS HP 30215A Magnetic Tape Controller Interface
05-Sep-17 JDB Changed REG_A (permit any symbolic override) to REG_X
12-Sep-16 JDB Changed DIB register macro usage from SRDATA to DIB_REG
09-Jun-16 JDB Added casts for ptrdiff_t to int32 values
08-Jun-16 JDB Corrected %d format to %u for unsigned values
@@ -514,7 +515,7 @@ static REG ms_reg [] = {
{ FLDATA (UINTRP, unit_interrupt, 0) },
{ FLDATA (DEVEND, device_end, 0) },
{ FLDATA (XFRERR, xfer_error, 0) },
{ ORDATA (BUFWRD, buffer_word, 16), REG_A | REG_FIT | PV_RZRO },
{ ORDATA (BUFWRD, buffer_word, 16), REG_X | REG_FIT | PV_RZRO },
{ DRDATA (ATUNIT, attention_unit, 16), REG_FIT | PV_LEFT },
{ DRDATA (CLASS, command_class, 4), PV_LEFT },
{ YRDATA (FLAGS, flags, 8, PV_RZRO) },

View File

@@ -1,6 +1,6 @@
SIMH/HP 3000 RELEASE NOTES
==========================
Last update: 2017-04-30
Last update: 2018-01-12
This file documents the release history of the Hewlett-Packard 3000 simulator.
@@ -47,7 +47,7 @@ General Information
The simulator passes the HP 32230 offline diagnostic suite with some expected
failures due to unimplemented features. For example, the disc diagnostic
error-correction logic tests and the tape diagnostic CRCC and LRCC tests fail,
as these features are not supported. However, all features that are required
as these features are not simulated. However, all features that are required
for MPE operation pass their respective diagnostic tests.
The simulator has been tested with MPE-V/R version E.01.00. Specifically:
@@ -176,6 +176,180 @@ the MPE version used:
=====================
Release 7, 2018-01-12
=====================
This release of the HP 3000 simulator adds the following features:
- Reading and writing to terminal sessions connected to the ATC have been
improved significantly. File uploads via Telnet using the Reflection
terminal emulator are now over 100 times faster than before, e.g., the
transfer time for a one-megabyte file has decreased from 69 minutes to 30
seconds. Block mode reads show similar speed improvements. Copy-and-paste
into the terminal window, Reflection file downloads, and output to the
terminal window in REMOTEACK mode show speed improvements of five to fifteen
times. Output in LOCALACK mode has been improved by around 50%.
- Information regarding Reflection file transfers and serial port disconnection
options has been added to Section 4.1.1, "Terminal Data Interface," of the HP
3000 Simulator User's Guide.
--------------------
Implementation Notes
--------------------
- File transfer using the Reflection terminal emulator requires an 8-bit data
path. To achieve this, the session must use MPE terminal type 12 (this may
be configured either during a system reload or by specifying the TERM=12
parameter when logging on with :HELLO), and the channel must be set to 8B,
REMOTEACK, and NOCAPSLOCK modes. Note that MPE's default terminal type 10
writes 7-bit data with odd parity, and characters with the parity bit on may
be displayed by the terminal emulator as extended characters in the Roman-8
symbol set. To avoid a garbled display when using the TERM=12 parameter to
override the default, the channel should be set to 8B mode after logging on
and back to 7B after logging off.
- The MPE-V/R software kit has been updated to increase the number of terminal
buffers per port from 3 to 5. Using the default of 3 may cause the system
to report "MPE Table TBUF has overflowed!!!" to the system console while
performing Reflection file uploads.
----------
Bugs Fixed
----------
1. PROBLEM: Serial port output stalls are not handled properly.
VERSION: Release 6.
OBSERVATION: The ATCD device supports I/O via host serial ports as well as
via Telnet connections. While output via Telnet works correctly, output
via serial ports fails. Attempting to output to the ATCD results in a few
characters written, and then the line hangs. Sometimes pressing ENTER at
the system console (ATCD channel 0) causes a few more characters to appear
on the serial terminal. Eventually, the line hangs permanently.
CAUSE: The terminal multiplexer library (sim_tmxr.c, part of the SIMH
framework) had provided a 256-byte output buffer for each line, independent
of the connection type (Telnet or serial). The library was changed to
reduce the serial buffer size to one byte. If the library output routine
receives the second character before the first one has been written to the
serial port, it returns SCPE_STALL status to indicate a buffer overflow.
The ATCD simulation correctly responds to this status by rescheduling the
output attempt. However, it fails to call the "tmxr_poll_tx" routine to
write to the serial port, so the rescheduled attempt fails as well.
RESOLUTION: Modify "line_service" (hp3000_atc.c) to call "tmxr_poll_tx" if
a buffer overflow occurs.
STATUS: Fixed in Release 7.
=====================
Release 6, 2017-09-07
=====================
This release of the HP 3000 simulator adds the following features:
- The new "-F" switch to the DETACH LP command forces an immediate detach,
regardless of the current paper position. This is the simulation equivalent
of physically removing the paper from the printer. Without the switch,
detaching is the equivalent of running out of paper, which permits printing
to continue to the end of the line (2613/17/18) or the page (2607) before the
printer goes offline.
- The HP 3000 Simulator User's Guide has been revised to add a new section
describing the simulator commands corresponding to hardware actions and to
rewrite the "Realistic, Calibrated, and Optimized Timing" section to describe
the three timing modes more clearly.
--------------------
Implementation Notes
--------------------
- The LP device's PCHR (punched channel character) and UPCHR (unpunched channel
character) registers have been renamed to PUNCHR and UNPCHR, respectively,
for compatibility with the HP 2100 simulator's LPT device.
- The manual clarifies that the display radix for shift counts, bit positions,
starting bits and counts, and the CIR values for the PAUS and HALT
instructions may be overridden with command-line switches.
----------
Bugs Fixed
----------
1. PROBLEM: Cancelling a deferred detach with ATTACH LP is rejected.
VERSION: Release 5.
OBSERVATION: The line printer "Unit Options" section of the HP 3000
Simulator User's Guide states that a DETACH LP command will be deferred if
there are characters in the print buffer. It further states that entering
ATTACH LP without specifying a filename will cancel the action. This does
not work. Entering ATTACH LP prints "Too few arguments" and does not alter
a pending detach.
CAUSE: The SCP routine "attach_cmd" checks for the presence of a filename
before calling the line printer simulator's "lp_attach" routine. If the
filename is omitted, "lp_attach" is never called to cancel the pending
detach.
RESOLUTION: Modify "lp_set_on_offline" (hp3000_lp.c) to cancel a deferred
detach, and modify the User's Guide to state that SET LP ONLINE is used to
cancel both the deferred offline and deferred detach actions.
STATUS: Fixed in Release 6.
2. PROBLEM: Changing printer models does not change the REALTIME delays.
VERSION: Release 5.
OBSERVATION: In REALTIME mode, the line printer simulator attempts to
model the print buffer load and print-and-space operation delays inherent
in the physical hardware. However, after setting a different model, the
buffer load, print, and paper advance times have not been changed.
CAUSE: The "lp_set_model" routine that is called in response to a "SET
LP <model>" command sets the realistic times to those of the current model
rather than those of the new model.
RESOLUTION: Modify "lp_set_model" (hp3000_lp.c) to use the new model value
to index into the realistic times array.
STATUS: Fixed in Release 6.
3. PROBLEM: Paper cannot be removed from a 2607 printer except at the TOF.
VERSION: Release 5.
OBSERVATION: Printing a few lines on a 2607 and then attempting to remove
the paper with the DETACH LP command displays "Command not completed" on
the simulation console. The file remains attached and therefore cannot be
manipulated externally.
CAUSE: The DETACH command simulates both running out of paper and removing
the paper from the printer. For the former, the 2607 continues to print
until the current form is complete (i.e., the top of what would be the next
form is reached). For the latter, the paper may be physically removed by
the operator while at any print position. The simulator incorrectly
forbids the latter operation unless the paper is positioned at the TOF.
RESOLUTION: Modify "lp_detach" (hp3000_lp.c) to add a "forced detach"
option ("DETACH -F LP") to detach the printer regardless of print position.
STATUS: Fixed in Release 6.
=====================
Release 5, 2017-04-30
=====================

View File

@@ -1,6 +1,6 @@
/* hp3000_sel.c: HP 3000 30030C Selector Channel simulator
Copyright (c) 2016, J. David Bryan
Copyright (c) 2016-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
@@ -25,6 +25,7 @@
SEL HP 3000 Series III Selector Channel
05-Sep-17 JDB Changed REG_A (permit any symbolic override) to REG_X
10-Oct-16 JDB Renumbered debug flags to start at 0
Added port_read_memory, port_write_memory macros
11-Jul-16 JDB Change "sel_unit" from a UNIT to an array of one UNIT
@@ -458,8 +459,8 @@ static REG sel_reg [] = {
{ ORDATA (CNBUF, control_buffer, 16), REG_FIT },
{ ORDATA (ADDR, address_word, 16), REG_FIT },
{ ORDATA (ADBUF, address_buffer, 16), REG_FIT },
{ ORDATA (INBUF, input_buffer, 16), REG_A | REG_FIT },
{ ORDATA (OUTBUF, output_buffer, 16), REG_A | REG_FIT },
{ ORDATA (INBUF, input_buffer, 16), REG_X | REG_FIT },
{ ORDATA (OUTBUF, output_buffer, 16), REG_X | REG_FIT },
{ NULL }
};

View File

@@ -23,6 +23,9 @@
in advertising or otherwise to promote the sale, use or other dealings in
this Software without prior written authorization from the author.
05-Sep-17 JDB Removed the -B (binary display) option; use -2 instead
Rewrote "fprint_sym" for better coverage
11-May-17 JDB Corrected comment in "fprint_value"
28-Apr-17 JDB Added void cast to "fprint_instruction" call for left stackop
03-Mar-17 JDB Added an implementation note to the "parse_sym" routine
29-Dec-16 JDB Changed the switch for STA format from -S to -T;
@@ -33,7 +36,7 @@
27-Sep-16 JDB Added COBOL firmware mnemonics
Modified "fprint_instruction" to handle two-word instructions
15-Sep-16 JDB Modified "one_time_init" to set aux_cmds "message" field
03-Sep-16 JDB Added the STOP_POWER and STOP_ARSINH messages
03-Sep-16 JDB Added the STOP_POWER and STOP_ARSINH status messages
01-Sep-16 JDB Moved the "hp_cold_cmd" routine to the CPU (as "cpu_cold_cmd")
Added the POWER command
03-Aug-16 JDB Improved "fmt_char" and "fmt_bitset" to allow multiple calls
@@ -100,6 +103,26 @@ extern DEVICE ms_dev; /* 7970 Magnetic Tape */
#define SCPE_OK_3_WORDS ((t_stat) -2) /* three words produced or consumed */
/* Symbolic mode and format override switches */
#define A_SWITCH SWMASK ('A')
#define B_SWITCH SWMASK ('B')
#define C_SWITCH SWMASK ('C')
#define D_SWITCH SWMASK ('D')
#define E_SWITCH SWMASK ('E')
#define H_SWITCH SWMASK ('H')
#define I_SWITCH SWMASK ('I')
#define M_SWITCH SWMASK ('M')
#define O_SWITCH SWMASK ('O')
#define T_SWITCH SWMASK ('T')
#define MODE_SWITCHES (C_SWITCH | E_SWITCH | I_SWITCH | M_SWITCH | T_SWITCH)
#define FORMAT_SWITCHES (A_SWITCH | B_SWITCH | D_SWITCH | H_SWITCH | O_SWITCH)
#define SYMBOLIC_SWITCHES (MODE_SWITCHES | A_SWITCH) /* -A is both a mode and a format switch */
#define ALL_SWITCHES (MODE_SWITCHES | FORMAT_SWITCHES)
/* Address parsing configuration flags */
typedef enum {
@@ -952,7 +975,7 @@ static t_stat hp_brk_cmd (int32 arg, CONST char *buf);
/* System interface local utility routines */
static void fprint_value (FILE *ofile, t_value val, uint32 radix, uint32 width, uint32 format);
static t_stat fprint_value (FILE *ofile, t_value val, uint32 radix, uint32 width, uint32 format);
static t_stat fprint_order (FILE *ofile, t_value *val, uint32 radix);
static t_stat fprint_subop (FILE *ofile, t_value *val, uint32 radix, t_addr addr, int32 switches);
static t_stat fprint_instruction (FILE *ofile, const OP_TABLE ops, t_value *val,
@@ -1177,58 +1200,85 @@ return SCPE_ARG; /* return an error if ca
/* Print a value in symbolic format.
Print the data value in the format specified by the optional switches on the
output stream supplied. This routine is called to print:
This routine prints a data value in the format specified by the optional
switches on the output stream provided. On entry, "ofile" is the opened
output stream, and the other parameters depend on the reason the routine was
called, as follows:
- the next instruction mnemonic when the simulator stops
- the result of EXAMining a register marked with a user flag
- the result of EXAMining a memory address
- the result of EVALuating a symbol
* To print the next instruction mnemonic when the simulator stops:
- addr = the program counter
- val = a pointer to sim_eval [0]
- uptr = NULL
- sw = "-M" | SIM_SW_STOP
On entry, "ofile" is the opened output stream, "addr" is respectively the
program counter, register radix and flags, memory address, or symbol index,
"val" is a pointer to an array of t_values of depth "sim_emax" representing
the value to be printed, "uptr" is respectively NULL, NULL, a pointer to the
named unit, or a pointer to the default unit, and "sw" contains any switches
passed on the command line. "sw" also includes SIM_SW_STOP for a simulator
stop call or SIM_SW_REG for a register call.
* To print the result of EXAMining a register with REG_VMIO or a user flag:
- addr = the ORed register radix and user flags
- val = a pointer to a single t_value
- uptr = NULL
- sw = the command line switches | SIM_SW_REG
* To print the result of EXAMining a memory address:
- addr = the memory address
- val = a pointer to sim_eval [0]
- uptr = a pointer to the named unit
- sw = the command line switches
* To print the result of EVALuating a symbol:
- addr = the symbol index
- val = a pointer to sim_eval [addr]
- uptr = a pointer to the default unit (cpu_unit)
- sw = the command line switches
On exit, a status code is returned to the caller. If the format requested is
not supported, SCPE_ARG status is returned, which causes the caller to print
the value in numeric format. Otherwise, SCPE_OK status is returned if a
single-word value was consumed, or the negative number of extra words (beyond
the first) consumed in printing the symbol is returned. For example,
printing a two-word symbol would return SCPE_OK_2_WORDS (= -1).
the value in numeric format with the default radix. Otherwise, SCPE_OK
status is returned if a single-word value was consumed, or the negative
number of extra words (beyond the first) consumed in printing the symbol is
returned. For example, printing a two-word symbol would return
SCPE_OK_2_WORDS (= -1).
The following symbolic formats are supported by the listed switches:
The following symbolic modes are supported by including the indicated
switches on the command line:
Switch Interpretation
Switch Display Interpretation
------ --------------------------------------------------
-a a single character in the right-hand byte
-b a 16-bit binary value
-c a two-character packed string
-e an EDIT instruction subprogram mnemonic
-i an I/O program instruction mnemonic
-m a CPU instruction mnemonic
-s a CPU status mnemonic
-A a single character in the right-hand byte
-C a two-character packed string
-E an EDIT instruction subprogram mnemonic
-ER an EDIT mnemonic starting with the right-hand byte
-I an I/O program instruction mnemonic
-M a CPU instruction mnemonic
-T a CPU status mnemonic
-o override numeric output to octal
-d override numeric output to decimal
-h override numeric output to hex
-r begin EDIT interpretation with the right-hand byte
In the absence of a mode switch, the value is displayed in a numeric format.
Memory may be displayed in any format. All registers may be overridden to
display in octal, decimal, or hexadecimal numeric format. Only registers
marked with the REG_A flag may be displayed in any format. Registers marked
with REG_B may be displayed in binary format. Registers marked with REG_M
will default to CPU instruction mnemonic display. Registers marked with
REG_T will default to CPU status mnemonic display.
When displaying data in one of the mnemonic modes, an additional switch may
be specified to indicate the desired operand format, as follows:
When displaying mnemonics, operand values are displayed in a radix suitable
to the type of the value. Address values are displayed in the CPU's address
radix, which is octal, and data values are displayed in the CPU's data radix,
which defaults to octal but may be set to a different radix or overridden by
a switch on the command line.
Switch Operand Interpretation
------ --------------------------------------------------
-A a single character in the right-hand byte
-B a binary value
-O an octal value
-D a decimal value
-H a hexadecimal value
Except for -B, these switches may be used without a mode switch to display a
numeric value in the specified form. To summarize, the valid switch
combinations are:
-A
-C
-E [ -R ] [ -A | -B | -O | -D | -H ]
-I [ -A | -B | -O | -D | -H ]
-M [ -A | -B | -O | -D | -H ]
-T [ -A | -B | -O | -D | -H ]
When displaying mnemonics, operand values by default are displayed in a radix
suitable to the type of the value. Address values are displayed in the CPU's
address radix, which is octal, and data values are displayed in the CPU's
data radix, which defaults to octal but may be set to a different radix or
overridden by a switch on the command line.
Implementation notes:
@@ -1241,76 +1291,116 @@ return SCPE_ARG; /* return an error if ca
2. Displaying a register having a symbolic default format (e.g., CIR) will
use the default unless the radix is overridden on the command line. For
example, "EXAMINE CIR" displays the CIR value as an instruction mnemonic,
whereas "EXAMINE -O CIR" displays the value as octal. Adding "-M" will
whereas "EXAMINE -D CIR" displays the value as decimal. Adding "-M" will
force mnemonic display and allow the radix switch to override the operand
display. For example, "EXAMINE -M -O CIR" displays the value as mnemonic
and overrides the operand radix to octal.
display. For example, "EXAMINE -M -D CIR" displays the value as mnemonic
and overrides the operand radix to decimal.
3. We return SCPE_INVSW when multiple modes or formats are specified, but
the callers do not act on this; they use the fallback formatter if any
status error is returned. We could work around this by printing "Invalid
switch" to the console and returning SCPE_OK, but this does not stop
IEXAMINE from prompting for the replacement value(s) or EXAMINE from
printing a range.
4. Radix switches and the -C switch are conceptually mutually exclusive.
However, if we return an error when "format" is non-zero, then -C will be
ignored, and the fallback formatter will use the radix switch. The other
choice is to process -C and ignore the radix switch; this is the option
implemented.
5. Because -A is both a mode and a format switch, we must check its presence
using SYMBOLIC_SWITCHES separately from the other modes to allow (e.g.)
both "EXAMINE -A" and "EXAMINE -M -A". If -A is added to MODE_SWITCHES,
the latter form would be rejected as having conflicting modes.
6. The penultimate condition of the multiway "if-else if" mode test checks
for no mode switches. This succeeds when -A is specified alone because
the earlier SYMBOLIC_SWITCHES test failed (so -A is present), but none of
the other mode switches are present.
*/
t_stat fprint_sym (FILE *ofile, t_addr addr, t_value *val, UNIT *uptr, int32 sw)
{
const t_bool is_reg = (sw & SIM_SW_REG) != 0; /* TRUE if this is a register access */
uint32 radix_override;
int32 formats, modes;
uint32 radix;
if (sw & SWMASK ('A') && (!is_reg || addr & REG_A)) /* if ASCII character display is requested and permitted */
if (val [0] <= D8_SMAX) { /* then if the value is a single character */
fputs (fmt_char ((uint32) val [0]), ofile); /* then format and print it */
return SCPE_OK;
}
if ((sw & (SIM_SW_REG | ALL_SWITCHES)) == SIM_SW_REG) /* if we are formatting a register without overrides */
if (addr & REG_A) /* then if the default format is character */
sw |= A_SWITCH; /* then set the -A switch */
else /* otherwise */
return SCPE_ARG; /* report that it cannot be displayed */
else if (addr & REG_C) /* otherwise if the default mode is string */
sw |= C_SWITCH; /* then set the -C switch */
else if (sw & SWMASK ('C') && (!is_reg || addr & REG_A)) { /* if ASCII string display is requested and permitted */
fputs (fmt_char (UPPER_BYTE (val [0])), ofile); /* then format and print the upper byte */
fputc (',', ofile); /* followed by a separator */
fputs (fmt_char (LOWER_BYTE (val [0])), ofile); /* then format and print the lower byte */
else if (addr & REG_M) /* otherwise if the default mode is instruction mnemonic */
sw |= M_SWITCH; /* then set the -M switch */
else if (addr & REG_T) /* otherwise if the default mode is status */
sw |= T_SWITCH; /* then set the -T switch */
if ((sw & SYMBOLIC_SWITCHES) == 0) /* if there are no symbolic mode overrides */
return SCPE_ARG; /* then return an error to use the standard formatter */
formats = sw & FORMAT_SWITCHES; /* separate the format switches */
modes = sw & MODE_SWITCHES; /* from the mode switches */
if (formats == A_SWITCH) /* if the -A switch is specified */
radix = 256; /* then override the radix to character */
else if (formats == B_SWITCH) /* otherwise if the -B switch is specified */
radix = 2; /* then override the radix to binary */
else if (formats == D_SWITCH) /* otherwise if the -D switch is specified */
radix = 10; /* then override the radix to decimal */
else if (formats == H_SWITCH) /* otherwise if the -H switch is specified */
radix = 16; /* then override the radix to hexadecimal */
else if (formats == O_SWITCH) /* otherwise if the -O switch is specified */
radix = 8; /* then override the radix to octal */
else if (formats == 0) /* otherwise if no format switch is specified */
radix = 0; /* then indicate that the default radix is to be used */
else /* otherwise more than one format is specified */
return SCPE_INVSW; /* so return an error */
if (modes == M_SWITCH) /* if mnemonic mode is specified */
return fprint_cpu (ofile, val, radix, sw); /* then format and print the value in mnemonic format */
else if (modes == I_SWITCH) /* otherwise if I/O channel order mode is specified */
return fprint_order (ofile, val, radix); /* then format and print it */
else if (modes == E_SWITCH) /* otherwise if an EDIT subop memory display is requested */
return fprint_subop (ofile, val, radix, addr, sw); /* then format and print it */
else if (modes == T_SWITCH) { /* otherwise if status display is requested */
fputs (fmt_status ((uint32) val [0]), ofile); /* then format the status flags and condition code */
fputc (' ', ofile); /* and add a separator */
if (fprint_value (ofile, STATUS_CS (val [0]), /* if the code segment number */
(radix ? radix : cpu_dev.dradix), /* prints with the specified radix */
STATUS_CS_WIDTH, PV_RZRO) == SCPE_OK)
return SCPE_OK; /* then return success */
else /* otherwise print it */
return fprint_val (ofile, STATUS_CS (val [0]), /* in the CPU's default data radix */
cpu_dev.dradix, D8_WIDTH, PV_RZRO);
}
else if (modes == C_SWITCH) { /* otherwise if ASCII string mode is specified */
fputs (fmt_char (UPPER_BYTE (val [0])), ofile); /* then format and print the upper byte */
fputc (',', ofile); /* followed by a separator */
fputs (fmt_char (LOWER_BYTE (val [0])), ofile); /* followed by the lower byte */
return SCPE_OK;
}
else if (sw & SWMASK ('B') /* if binary display is requested */
&& (!is_reg || addr & (REG_A | REG_B))) { /* and is permitted */
fprint_val (ofile, val [0], 2, DV_WIDTH, PV_RZRO); /* then format and print the value */
return SCPE_OK;
}
else if (modes == 0) /* otherwise if single-character mode was specified */
return fprint_value (ofile, val [0], radix, 0, 0); /* then format and print it */
else { /* otherwise display as numeric or mnemonic */
if (sw & SWMASK ('O')) /* if an octal override is present */
radix_override = 8; /* then print the value in base 8 */
else if (sw & SWMASK ('D')) /* otherwise if a decimal override is present */
radix_override = 10; /* then print the value in base 10 */
else if (sw & SWMASK ('H')) /* otherwise if a hex override is present */
radix_override = 16; /* then print the value in base 16 */
else /* otherwise */
radix_override = 0; /* use the default radix setting */
if (sw & SWMASK ('I') && !is_reg) /* if I/O channel order memory display is requested */
return fprint_order (ofile, val, radix_override); /* then format and print it */
else if (sw & SWMASK ('E') && !is_reg) /* otherwise if an EDIT subop memory display is requested */
return fprint_subop (ofile, val, radix_override, addr, sw);
else if (sw & SWMASK ('M') /* otherwise if CPU instruction display is requested */
&& (!is_reg || addr & (REG_A | REG_M)) /* and is permitted */
|| is_reg && addr & REG_M && radix_override == 0) /* or if displaying a register that defaults to mnemonic */
return fprint_cpu (ofile, val, radix_override, sw); /* then format and print it */
else if (sw & SWMASK ('T') /* otherwise if status display is requested */
&& (!is_reg || addr & (REG_A | REG_T)) /* and is permitted */
|| is_reg && addr & REG_T && radix_override == 0) { /* or if displaying a register that defaults to status */
fputs (fmt_status ((uint32) val [0]), ofile); /* then format the status flags and condition code */
fputc (' ', ofile); /* and add a separator */
fprint_value (ofile, STATUS_CS (val [0]), /* print the code segment number */
(radix_override ? radix_override : cpu_dev.dradix),
STATUS_CS_WIDTH, PV_RZRO);
return SCPE_OK;
}
else /* otherwise */
return SCPE_ARG; /* request that the value be printed numerically */
}
else /* otherwise the modes conflict */
return SCPE_INVSW; /* so return an error */
}
@@ -2025,11 +2115,11 @@ return formatted; /* return a pointer to t
/* Format a character for printing.
This routine formats single 8-bit character value into a printable string and
returns a pointer to that string. Printable characters retain their original
form but are enclosed in single quotes. Control characters are translated to
readable strings. Characters outside of the ASCII range are presented as
escaped octal values.
This routine formats a single 8-bit character value into a printable string
and returns a pointer to that string. Printable characters retain their
original form but are enclosed in single quotes. Control characters are
translated to readable strings. Characters outside of the ASCII range are
presented as escaped octal values.
Implementation notes:
@@ -2914,24 +3004,39 @@ return status; /* return the handler st
/* System interface local utility routines */
/* Print a numeric value with a radix identifier.
/* Print a numeric value in a given radix with a radix identifier.
This routine prints a numeric value with a leading radix indicator if the
specified print radix is not the same as the current CPU data radix. It uses
the HP 3000 convention of a leading "%", "#", or "!" character to indicate
an octal, decimal, or hexadecimal number.
This routine prints a numeric value using the specified radix, width, and
output format. If the radix is 256, then the value is printed as a single
character. Otherwise, it is printed as a numeric value with a leading radix
indicator if the specified print radix is not the same as the current CPU
data radix. It uses the HP 3000 convention of a leading "%", "#", or "!"
character to indicate an octal, decimal, or hexadecimal number (there is no
binary convention, so a leading "@" is used arbitrarily).
On entry, the "ofile" parameter is the opened output stream, "val" is the
value to print, "radix" is the desired print radix, "width" is the number of
significant bits in the value, and "format" is a format specifier (PV_RZRO,
PV_RSPC, or PV_LEFT). On exit, the status of the print operation is
returned.
PV_RSPC, or PV_LEFT). On exit, the routine returns SCPE_OK if the value was
printed successfully, or SCPE_ARG if the value could not be printed.
*/
static void fprint_value (FILE *ofile, t_value val, uint32 radix, uint32 width, uint32 format)
static t_stat fprint_value (FILE *ofile, t_value val, uint32 radix, uint32 width, uint32 format)
{
if (radix != cpu_dev.dradix) /* if the requested radix is not the current data radix */
if (radix == 8) /* then if the requested radix is octal */
if (radix == 256) /* if ASCII character display is requested */
if (val <= D8_SMAX) { /* then if the value is a single character */
fputs (fmt_char ((uint32) val), ofile); /* then format and print it */
return SCPE_OK; /* and report success */
}
else /* otherwise */
return SCPE_ARG; /* report that it cannot be displayed */
else if (radix != cpu_dev.dradix) /* otherwise if the requested radix is not the current data radix */
if (radix == 2) /* then if the requested radix is binary */
fputc ('@', ofile); /* then print the binary indicator */
else if (radix == 8) /* otherwise if the requested radix is octal */
fputc ('%', ofile); /* then print the octal indicator */
else if (radix == 10) /* otherwise if it is decimal */
@@ -2945,7 +3050,7 @@ if (radix != cpu_dev.dradix) /* if the requested radi
fprint_val (ofile, val, radix, width, format); /* print the value in the radix specified */
return;
return SCPE_OK; /* return success */
}
@@ -2979,16 +3084,15 @@ return;
- Address values are printed in the CPU's address radix, which is octal.
- Counts are printed in decimal.
- Counts are printed by default in decimal.
- Control and status values are printed in the CPU's data radix, which
defaults to octal but may be set to a different radix with SET CPU
OCT|DEC|HEX.
defaults to octal.
The radix for operand values other than addresses may be overridden by a
switch on the command line. A value printed in a radix other than the
current data radix is preceded by a radix identifier ("%" for octal, "#" for
decimal, or "!" for hexadecimal).
current data radix is preceded by a radix identifier ("@" for binary, "%" for
octal, "#" for decimal, or "!" for hexadecimal).
The routine returns SCPE_OK_2_WORDS to indicate that two words were consumed.
@@ -3031,7 +3135,7 @@ switch (order) { /* dispatch operand prin
case sioJUMP:
case sioJUMPC: /* print the jump target address */
fprint_value (ofile, ioaw, cpu_dev.aradix,
fprint_value (ofile, ioaw, cpu_dev.aradix, /* in the CPU's address radix */
LA_WIDTH, PV_RZRO);
break;
@@ -3042,7 +3146,7 @@ switch (order) { /* dispatch operand prin
break;
case sioSBANK: /* print the bank address */
fprint_value (ofile, ioaw & BA_MASK,
fprint_value (ofile, ioaw & BA_MASK, /* in the CPU's address radix */
cpu_dev.aradix, BA_WIDTH, PV_RZRO);
break;
@@ -3078,7 +3182,7 @@ switch (order) { /* dispatch operand prin
fputc (',', ofile);
fprint_value (ofile, ioaw, cpu_dev.aradix,
fprint_value (ofile, ioaw, cpu_dev.aradix, /* prnit the address in the CPU's address radix */
LA_WIDTH, PV_RZRO);
break;
}
@@ -3562,7 +3666,6 @@ switch (ops [op_index].operand) { /* dispatch by the opera
prefix = " "; /* so just use a space to separate the value */
op_value = (op_value & ~op_mask [opS11]) >> EIS_SDEC_SHIFT; /* remove the flags from the S decrement value */
op_radix = (radix ? radix : cpu_dev.dradix); /* and set the print radix */
break;

View File

@@ -1,6 +1,6 @@
/* hp_disclib.h: HP MAC/ICD disc controller simulator library declarations
Copyright (c) 2011-2016, J. David Bryan
Copyright (c) 2011-2017, J. David Bryan
Copyright (c) 2004-2011, Robert M. Supnik
Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -24,6 +24,7 @@
in advertising or otherwise to promote the sale, use or other dealings in
this Software without prior written authorization from the authors.
05-Sep-17 JDB Changed REG_A (permit any symbolic override) to REG_X
10-Oct-16 JDB Moved "hp3000_defs.h" inclusion to "hp_disclib.c"
13-May-16 JDB Modified for revised SCP API function parameter types
24-Mar-16 JDB Added the DL_BUFFER type to define the disc buffer array
@@ -479,7 +480,7 @@ typedef CNTLR_VARS *CVPTR; /* pointer to a controller state
{ DRDATA (HEAD, (cntlr).head, 6), PV_LEFT }, \
{ DRDATA (SECTOR, (cntlr).sector, 8), PV_LEFT }, \
{ DRDATA (COUNT, (cntlr).count, 16), PV_LEFT }, \
{ BRDATA (SECBUF, (buffer), 8, 16, DL_BUFSIZE), REG_A }, \
{ BRDATA (SECBUF, (buffer), 8, 16, DL_BUFSIZE), REG_X }, \
{ DRDATA (INDEX, (cntlr).index, 8), PV_LEFT }, \
{ DRDATA (LENGTH, (cntlr).length, 8), PV_LEFT }, \
{ DRDATA (POLLU, (cntlr).poll_unit, 4), REG_HRO }, \

View File

@@ -1,6 +1,6 @@
/* hp_tapelib.h: HP magnetic tape controller simulator library declarations
Copyright (c) 2013-2016, J. David Bryan
Copyright (c) 2013-2017, J. David Bryan
Copyright (c) 2004-2011, Robert M. Supnik
Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -24,6 +24,7 @@
in advertising or otherwise to promote the sale, use or other dealings in
this Software without prior written authorization from the authors.
05-Sep-17 JDB Changed REG_A (permit any symbolic override) to REG_X
10-Oct-16 JDB Moved "hp3000_defs.h" inclusion to "hp_tapelib.c"
13-May-16 JDB Modified for revised SCP API function parameter types
24-Mar-16 JDB Added the TL_BUFFER type to define the tape buffer array
@@ -419,7 +420,7 @@ typedef CNTLR_VARS *CVPTR; /* a pointer to a controller sta
{ ORDATA (STATUS, (cntlr).status, 16), REG_RO }, \
{ DRDATA (USEL, (cntlr).unit_selected, 4), PV_LEFT | REG_RO }, \
{ YRDATA (UATTN, (cntlr).unit_attention, 4, PV_RZRO) }, \
{ BRDATA (RECBUF, (buffer), 8, 8, TL_BUFSIZE), REG_A }, \
{ BRDATA (RECBUF, (buffer), 8, 8, TL_BUFSIZE), REG_X }, \
{ DRDATA (LIBSTA, (cntlr).call_status, 16), PV_LEFT }, \
{ DRDATA (LENGTH, (cntlr).length, 24), PV_LEFT }, \
{ DRDATA (INDEX, (cntlr).index, 24), PV_LEFT }, \

Binary file not shown.