simh v2.6a

This commit is contained in:
Bob Supnik 2001-11-06 20:54:00 -08:00 committed by Mark Pizzolato
parent 4d6dfa4bdb
commit a7b623a1a8
40 changed files with 1793 additions and 901 deletions

View file

@ -30,6 +30,7 @@ extern unsigned int32 get_uint (char *cptr, int32 radix, unsigned int32 max,
sim_PC pointer to saved PC register descriptor
sim_emax number of words needed for examine
sim_devices array of pointers to simulated devices
sim_consoles array of pointers to consoles (if more than one)
sim_stop_messages array of pointers to stop messages
sim_load binary loader
*/
@ -43,6 +44,8 @@ int32 sim_emax = 4;
DEVICE *sim_devices[] = { &cpu_dev, &sio_dev, &ptr_dev,
&ptp_dev, &dsk_dev, NULL };
UNIT *sim_consoles = NULL;
const char *sim_stop_messages[] = {
"Unknown error",
"Unknown I/O Instruction",

View file

@ -28,6 +28,7 @@
cpu Eclipse central processor
01-Jun-01 RMS Added second terminal, plotter support
26-Apr-01 RMS Added device enable/disable support
The register state for the Eclipse CPU is basically the same as
@ -436,7 +437,10 @@ extern int32 ptr (int32 pulse, int32 code, int32 AC);
extern int32 ptp (int32 pulse, int32 code, int32 AC);
extern int32 tti (int32 pulse, int32 code, int32 AC);
extern int32 tto (int32 pulse, int32 code, int32 AC);
extern int32 tti1 (int32 pulse, int32 code, int32 AC);
extern int32 tto1 (int32 pulse, int32 code, int32 AC);
extern int32 clk (int32 pulse, int32 code, int32 AC);
extern int32 plt (int32 pulse, int32 code, int32 AC);
extern int32 lpt (int32 pulse, int32 code, int32 AC);
extern int32 dsk (int32 pulse, int32 code, int32 AC);
extern int32 dkp (int32 pulse, int32 code, int32 AC);
@ -455,7 +459,7 @@ struct ndev dev_table[64] = {
{ 0, 0, &nulldev }, { 0, 0, &nulldev },
{ INT_TTI, PI_TTI, &tti }, { INT_TTO, PI_TTO, &tto }, /* 10 - 17 */
{ INT_PTR, PI_PTR, &ptr }, { INT_PTP, PI_PTP, &ptp },
{ INT_CLK, PI_CLK, &clk }, { 0, 0, &nulldev },
{ INT_CLK, PI_CLK, &clk }, { INT_PLT, PI_PLT, &plt },
{ 0, 0, &nulldev }, { INT_LPT, PI_LPT, &lpt },
{ INT_DSK, PI_DSK, &dsk }, { 0, 0, &nulldev }, /* 20 - 27 */
{ INT_MTA, PI_MTA, &mta }, { 0, 0, &nulldev },
@ -469,7 +473,7 @@ struct ndev dev_table[64] = {
{ 0, 0, &nulldev }, { 0, 0, &nulldev },
{ 0, 0, &nulldev }, { 0, 0, &nulldev },
{ 0, 0, &nulldev }, { 0, 0, &nulldev },
{ 0, 0, &nulldev }, { 0, 0, &nulldev }, /* 50 - 57 */
{ INT_TTI1, PI_TTI1, &tti1 }, { INT_TTO1, PI_TTO1, &tto1 }, /* 50 - 57 */
{ 0, 0, &nulldev }, { 0, 0, &nulldev },
{ 0, 0, &nulldev }, { 0, 0, &nulldev },
{ 0, 0, &nulldev }, { 0, 0, &nulldev },

View file

@ -23,6 +23,7 @@
be used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from Robert M Supnik.
27-May-01 RMS Added multiconsole support
14-Mar-01 RMS Revised load/dump interface (again)
30-Oct-00 RMS Added examine to file support
15-Oct-00 RMS Added dynamic device number support
@ -48,6 +49,7 @@ extern uint16 M[];
sim_PC pointer to saved PC register descriptor
sim_emax maximum number of words for examine/deposit
sim_devices array of pointers to simulated devices
sim_consoles array of pointers to consoles (if more than one)
sim_stop_messages array of pointers to stop messages
sim_load binary loader
*/
@ -67,6 +69,8 @@ DEVICE *sim_devices[] = { &cpu_dev,
&dpd_dev, &dpc_dev,
NULL };
UNIT *sim_consoles = NULL;
const char *sim_stop_messages[] = {
"Unknown error",
"Unimplemented instruction",

View file

@ -23,6 +23,7 @@
be used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from Robert M Supnik.
27-May-01 RMS Added multiconsole support
14-Mar-01 RMS Revised load/dump interface (again)
30-Oct-00 RMS Added support for examine to file
27-Oct-98 RMS V2.4 load interface
@ -50,6 +51,7 @@ extern int32 store_addr_u (int32 addr);
sim_PC pointer to saved PC register descriptor
sim_emax maximum number of words for examine/deposit
sim_devices array of pointers to simulated devices
sim_consoles array of pointers to consoles (if more than one)
sim_stop_messages array of pointers to stop messages
sim_load binary loader
*/
@ -64,6 +66,8 @@ DEVICE *sim_devices[] = { &cpu_dev, &inq_dev,
&cdr_dev, &cdp_dev, &stack_dev, &lpt_dev,
&mt_dev, NULL };
UNIT *sim_consoles = NULL;
const char *sim_stop_messages[] = {
"Unknown error",
"Unimplemented instruction",

View file

@ -23,6 +23,7 @@
be used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from Robert M Supnik.
27-May-01 RMS Added multiconsole support
14-Mar-01 RMS Revised load/dump interface (again)
30-Oct-00 RMS Added support for examine to file
27-Oct-98 RMS V2.4 load interface
@ -44,6 +45,7 @@ extern int32 saved_PC;
sim_PC pointer to saved PC register descriptor
sim_emax number of words for examine
sim_devices array of pointers to simulated devices
sim_consoles array of pointers to consoles (if more than one)
sim_stop_messages array of pointers to stop messages
sim_load binary loader
*/
@ -58,6 +60,8 @@ DEVICE *sim_devices[] = { &cpu_dev,
&pt_dev, &tt_dev,
NULL };
UNIT *sim_consoles = NULL;
const char *sim_stop_messages[] = {
"Unknown error",
"Reserved instruction",

View file

@ -23,6 +23,7 @@
be used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from Robert M Supnik.
31-May-01 RMS Added multiconsole support
14-Mar-01 RMS Revised load/dump interface (again)
22-Dec-00 RMS Added second terminal support
10-Dec-00 RMS Added Eclipse support
@ -31,7 +32,7 @@
15-Oct-00 RMS Added stack, byte, trap instructions
14-Apr-99 RMS Changed t_addr to unsigned
27-Oct-98 RMS V2.4 load interface
24-Sep-97 RMS Fixed bug in device name table (found by Dutch Owen)
24-Sep-97 RMS Fixed bug in device name table (found by Charles Owen)
*/
#include "nova_defs.h"
@ -49,6 +50,8 @@ extern DEVICE tti1_dev, tto1_dev;
extern DEVICE clk_dev, lpt_dev;
extern DEVICE dkp_dev, dsk_dev;
extern DEVICE mta_dev;
extern UNIT tti_unit, tto_unit;
extern UNIT tti1_unit, tto1_unit;
extern REG cpu_reg[];
extern uint16 M[];
extern int32 saved_PC;
@ -59,6 +62,7 @@ extern int32 saved_PC;
sim_PC pointer to saved PC register descriptor
sim_emax number of words needed for examine
sim_devices array of pointers to simulated devices
sim_consoles array of pointers to consoles (if more than one)
sim_stop_messages array of pointers to stop messages
sim_load binary loader
*/
@ -86,6 +90,11 @@ DEVICE *sim_devices[] = {
&dkp_dev, &mta_dev,
NULL };
UNIT *sim_consoles[] = {
&tti_unit, &tto_unit,
&tti1_unit, &tto1_unit,
NULL };
const char *sim_stop_messages[] = {
"Unknown error",
"Unknown I/O instruction",

View file

@ -25,6 +25,8 @@
tti terminal input
tto terminal output
31-May-01 RMS Added multiconsole support
*/
#include "nova_defs.h"
@ -39,6 +41,7 @@ t_stat tto_reset (DEVICE *dptr);
t_stat ttx_setmod (UNIT *uptr, int32 value);
extern t_stat sim_poll_kbd (void);
extern t_stat sim_putchar (int32 out);
static uint8 tto_consout[CONS_SIZE];
/* TTI data structures
@ -48,7 +51,7 @@ extern t_stat sim_putchar (int32 out);
ttx_mod TTI/TTO modifiers list
*/
UNIT tti_unit = { UDATA (&tti_svc, 0, 0), KBD_POLL_WAIT };
UNIT tti_unit = { UDATA (&tti_svc, UNIT_CONS, 0), KBD_POLL_WAIT };
REG tti_reg[] = {
{ ORDATA (BUF, tti_unit.buf, 8) },
@ -59,9 +62,12 @@ REG tti_reg[] = {
{ DRDATA (POS, tti_unit.pos, 31), PV_LEFT },
{ DRDATA (TIME, tti_unit.wait, 24), REG_NZ + PV_LEFT },
{ FLDATA (MODE, tti_unit.flags, UNIT_V_DASHER), REG_HRO },
{ FLDATA (CFLAG, tti_unit.flags, UNIT_V_CONS), REG_HRO },
{ NULL } };
MTAB ttx_mod[] = {
{ UNIT_CONS, 0, "inactive", NULL, NULL },
{ UNIT_CONS, UNIT_CONS, "active console", "CONSOLE", &set_console },
{ UNIT_DASHER, 0, "ANSI", "ANSI", &ttx_setmod },
{ UNIT_DASHER, UNIT_DASHER, "Dasher", "DASHER", &ttx_setmod },
{ 0 } };
@ -79,7 +85,7 @@ DEVICE tti_dev = {
tto_reg TTO register list
*/
UNIT tto_unit = { UDATA (&tto_svc, 0, 0), SERIAL_OUT_WAIT };
UNIT tto_unit = { UDATA (&tto_svc, UNIT_CONS, 0), SERIAL_OUT_WAIT };
REG tto_reg[] = {
{ ORDATA (BUF, tto_unit.buf, 8) },
@ -90,6 +96,8 @@ REG tto_reg[] = {
{ DRDATA (POS, tto_unit.pos, 31), PV_LEFT },
{ DRDATA (TIME, tto_unit.wait, 24), PV_LEFT },
{ FLDATA (MODE, tto_unit.flags, UNIT_V_DASHER), REG_HRO },
{ BRDATA (CONSOUT, tto_consout, 8, 8, CONS_SIZE), REG_HIDDEN },
{ FLDATA (CFLAG, tto_unit.flags, UNIT_V_CONS), REG_HRO },
{ NULL } };
DEVICE tto_dev = {
@ -145,7 +153,8 @@ tti_unit.buf = 0;
dev_busy = dev_busy & ~INT_TTI; /* clear busy */
dev_done = dev_done & ~INT_TTI; /* clear done, int */
int_req = int_req & ~INT_TTI;
sim_activate (&tti_unit, tti_unit.wait); /* activate unit */
if (tti_unit.flags & UNIT_CONS) /* if active console, */
sim_activate (&tti_unit, tti_unit.wait); /* activate unit */
return SCPE_OK;
}
@ -181,7 +190,7 @@ dev_done = dev_done | INT_TTO; /* set done */
int_req = (int_req & ~INT_DEV) | (dev_done & ~dev_disable);
c = tto_unit.buf & 0177;
if ((tto_unit.flags & UNIT_DASHER) && (c == 031)) c = '\b';
if ((temp = sim_putchar (c)) != SCPE_OK) return temp;
if ((temp = sim_putcons (c, uptr)) != SCPE_OK) return temp;
tto_unit.pos = tto_unit.pos + 1;
return SCPE_OK;
}
@ -195,6 +204,7 @@ dev_busy = dev_busy & ~INT_TTO; /* clear busy */
dev_done = dev_done & ~INT_TTO; /* clear done, int */
int_req = int_req & ~INT_TTO;
sim_cancel (&tto_unit); /* deactivate unit */
tto_unit.filebuf = tto_consout; /* set buf pointer */
return SCPE_OK;
}

View file

@ -27,6 +27,7 @@
tti1 second terminal input
tto1 second terminal output
31-May-01 RMS Added multiconsole support
26-Apr-01 RMS Added device enable/disable support
*/
@ -36,14 +37,13 @@
#define UNIT_DASHER (1 << UNIT_V_DASHER)
extern int32 int_req, dev_busy, dev_done, dev_disable, iot_enb;
int32 tti1_stopioe = 0, tto1_stopioe = 0; /* stop on error */
t_stat tti1_svc (UNIT *uptr);
t_stat tto1_svc (UNIT *uptr);
t_stat tti1_reset (DEVICE *dptr);
t_stat tto1_reset (DEVICE *dptr);
t_stat tti1_attach (UNIT *uptr, char *ptr);
t_stat tti1_detach (UNIT *uptr);
t_stat ttx1_setmod (UNIT *uptr, int32 value);
extern t_stat sim_poll_kbd (void);
static uint8 tto1_consout[CONS_SIZE];
/* TTI1 data structures
@ -53,7 +53,7 @@ t_stat ttx1_setmod (UNIT *uptr, int32 value);
ttx1_mod TTI1/TTO1 modifiers list
*/
UNIT tti1_unit = { UDATA (&tti1_svc, UNIT_SEQ+UNIT_ATTABLE, 0), KBD_POLL_WAIT };
UNIT tti1_unit = { UDATA (&tti1_svc, 0, 0), KBD_POLL_WAIT };
REG tti1_reg[] = {
{ ORDATA (BUF, tti1_unit.buf, 8) },
@ -63,12 +63,14 @@ REG tti1_reg[] = {
{ FLDATA (INT, int_req, INT_V_TTI1) },
{ DRDATA (POS, tti1_unit.pos, 31), PV_LEFT },
{ DRDATA (TIME, tti1_unit.wait, 24), REG_NZ + PV_LEFT },
{ FLDATA (STOP_IOE, tti1_stopioe, 0) },
{ FLDATA (MODE, tti1_unit.flags, UNIT_V_DASHER), REG_HRO },
{ FLDATA (CFLAG, tti1_unit.flags, UNIT_V_CONS), REG_HRO },
{ FLDATA (*DEVENB, iot_enb, INT_V_TTI1), REG_HRO },
{ NULL } };
MTAB ttx1_mod[] = {
{ UNIT_CONS, 0, "inactive", NULL, NULL },
{ UNIT_CONS, UNIT_CONS, "active console", "CONSOLE", &set_console },
{ UNIT_DASHER, 0, "ANSI", "ANSI", &ttx1_setmod },
{ UNIT_DASHER, UNIT_DASHER, "Dasher", "DASHER", &ttx1_setmod },
{ 0 } };
@ -77,7 +79,7 @@ DEVICE tti1_dev = {
"TTI1", &tti1_unit, tti1_reg, ttx1_mod,
1, 10, 31, 1, 8, 8,
NULL, NULL, &tti1_reset,
NULL, &tti1_attach, &tti1_detach };
NULL, NULL, NULL };
/* TTO1 data structures
@ -86,7 +88,7 @@ DEVICE tti1_dev = {
tto1_reg TTO1 register list
*/
UNIT tto1_unit = { UDATA (&tto1_svc, UNIT_SEQ+UNIT_ATTABLE, 0), SERIAL_OUT_WAIT };
UNIT tto1_unit = { UDATA (&tto1_svc, 0, 0), SERIAL_OUT_WAIT };
REG tto1_reg[] = {
{ ORDATA (BUF, tto1_unit.buf, 8) },
@ -96,8 +98,9 @@ REG tto1_reg[] = {
{ FLDATA (INT, int_req, INT_V_TTO1) },
{ DRDATA (POS, tto1_unit.pos, 31), PV_LEFT },
{ DRDATA (TIME, tto1_unit.wait, 24), PV_LEFT },
{ FLDATA (STOP_IOE, tto1_stopioe, 0) },
{ FLDATA (MODE, tto1_unit.flags, UNIT_V_DASHER), REG_HRO },
{ BRDATA (CONSOUT, tto1_consout, 8, 8, CONS_SIZE), REG_HIDDEN },
{ FLDATA (CFLAG, tto1_unit.flags, UNIT_V_CONS), REG_HRO },
{ FLDATA (*DEVENB, iot_enb, INT_V_TTI1), REG_HRO },
{ NULL } };
@ -134,16 +137,8 @@ t_stat tti1_svc (UNIT *uptr)
{
int32 temp;
if ((tti1_unit.flags & UNIT_ATT) == 0) /* attached? */
return IORETURN (tti1_stopioe, SCPE_UNATT);
sim_activate (&tti1_unit, tti1_unit.wait); /* continue poll */
if ((temp = getc (tti1_unit.fileref)) == EOF) { /* end of file? */
if (feof (tti1_unit.fileref)) {
if (tti1_stopioe) printf ("TTI1 end of file\n");
else return SCPE_OK; }
else perror ("TTI1 input error");
clearerr (tti1_unit.fileref);
return SCPE_IOERR; }
if ((temp = sim_poll_kbd ()) < SCPE_KFLAG) return temp; /* no char or error? */
tti1_unit.buf = temp & 0177;
if ((tti1_unit.flags & UNIT_DASHER) && (tti1_unit.buf == '\r'))
tti1_unit.buf = '\n'; /* Dasher: cr -> nl */
@ -162,30 +157,10 @@ tti1_unit.buf = 0;
dev_busy = dev_busy & ~INT_TTI1; /* clear busy */
dev_done = dev_done & ~INT_TTI1; /* clear done, int */
int_req = int_req & ~INT_TTI1;
if (tti1_unit.flags & UNIT_ATT) /* attached? */
if (tti1_unit.flags & UNIT_CONS) /* active console? */
sim_activate (&tti1_unit, tti1_unit.wait);
else sim_cancel (&tti1_unit);
return SCPE_OK;
}
/* Attach routine */
t_stat tti1_attach (UNIT *uptr, char *cptr)
{
t_stat reason;
reason = attach_unit (uptr, cptr);
if (reason == SCPE_OK) sim_activate (uptr, uptr -> wait);
return reason;
}
/* Detach routine */
t_stat tti1_detach (UNIT *uptr)
{
sim_cancel (uptr);
return detach_unit (uptr);
}
/* Terminal output: IOT routine */
@ -212,19 +187,14 @@ return 0;
t_stat tto1_svc (UNIT *uptr)
{
int32 c ;
int32 c, temp;
dev_busy = dev_busy & ~INT_TTO1; /* clear busy */
dev_done = dev_done | INT_TTO1; /* set done */
int_req = (int_req & ~INT_DEV) | (dev_done & ~dev_disable);
if ((tto1_unit.flags & UNIT_ATT) == 0) /* attached? */
return IORETURN (tto1_stopioe, SCPE_UNATT);
c = tto1_unit.buf & 0177;
if ((tto1_unit.flags & UNIT_DASHER) && (c == 031)) c = '\b';
if (putc (c, tto1_unit.fileref) == EOF) {
perror ("TTO1 output error");
clearerr (tto1_unit.fileref);
return SCPE_IOERR; }
if ((temp = sim_putcons (c, uptr)) != SCPE_OK) return temp;
tto1_unit.pos = tto1_unit.pos + 1;
return SCPE_OK;
}
@ -238,6 +208,7 @@ dev_busy = dev_busy & ~INT_TTO1; /* clear busy */
dev_done = dev_done & ~INT_TTO1; /* clear done, int */
int_req = int_req & ~INT_TTO1;
sim_cancel (&tto1_unit); /* deactivate unit */
tto1_unit.filebuf = tto1_consout; /* set buf pointer */
return SCPE_OK;
}

View file

@ -25,6 +25,7 @@
cpu KS10 central processor
19-May-01 RMS Added workaround for TOPS-20 V4.1 boot bug
29-Apr-01 RMS Fixed modifier naming conflict
Fixed XCTR/XCTRI, UMOVE/UMOVEM, BLTUB/BLTBU for ITS
Added CLRCSH for ITS
@ -115,7 +116,7 @@
#define ILL_ADR_FLAG (1 << VASIZE)
#define save_ibkpt (cpu_unit.u3)
#define UNIT_V_MSIZE (UNIT_V_ITS + 1) /* dummy mask */
#define UNIT_V_MSIZE (UNIT_V_T20V41 + 1) /* dummy mask */
#define UNIT_MSIZE (1 << UNIT_V_MSIZE)
d10 *M = NULL; /* memory */
@ -241,6 +242,7 @@ REG cpu_reg[] = {
{ DRDATA (INDMAX, ind_max, 8), PV_LEFT + REG_NZ },
{ DRDATA (XCTMAX, xct_max, 8), PV_LEFT + REG_NZ },
{ FLDATA (ITS, cpu_unit.flags, UNIT_V_ITS), REG_HRO },
{ FLDATA (T20V41, cpu_unit.flags, UNIT_V_T20V41), REG_HRO },
{ ORDATA (BREAK, ibkpt_addr, VASIZE + 1) },
{ ORDATA (WRU, sim_int_char, 8) },
{ FLDATA (STOP_ILL, stop_op0, 0) },
@ -248,8 +250,9 @@ REG cpu_reg[] = {
{ NULL } };
MTAB cpu_mod[] = {
{ UNIT_ITS, 0, "Standard microcode", "STANDARD", NULL },
{ UNIT_ITS, UNIT_ITS, "ITS microcode", "ITS", NULL },
{ UNIT_ITS+UNIT_T20V41, 0, "Standard microcode", "STANDARD", NULL },
{ UNIT_ITS+UNIT_T20V41, UNIT_T20V41, "TOPS-20 V4.1", "TOPS20V41", NULL },
{ UNIT_ITS+UNIT_T20V41, UNIT_ITS, "ITS microcode", "ITS", NULL },
{ 0 } };
DEVICE cpu_dev = {

View file

@ -22,6 +22,9 @@
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.
01-Jun-01 RMS Updated DZ11 vector definitions
19-May-01 RMS Added workaround for TOPS-20 V4.1 boot bug
*/
#include "sim_defs.h" /* simulator defns */
@ -103,6 +106,8 @@ typedef int64 d10; /* PDP-10 data (36b) */
#define UNIT_V_ITS (UNIT_V_UF) /* ITS */
#define UNIT_ITS (1 << UNIT_V_ITS)
#define UNIT_V_T20V41 (UNIT_V_UF + 1) /* TOPS-20 V4.1 */
#define UNIT_T20V41 (1 << UNIT_V_T20V41)
#define ITS (cpu_unit.flags & UNIT_ITS)
/* Architectural constants */
@ -590,22 +595,24 @@ typedef int64 d10; /* PDP-10 data (36b) */
/* I/O system definitions, lifted from the PDP-11 simulator
Interrupt assignments, priority is right to left
<7:0> = BR7
<15:8> = BR6
<23:16> = BR5
<30:24> = BR4
<3:0> = BR7
<7:4> = BR6
<19:8> = BR5
<30:20> = BR4
*/
#define INT_V_RP 8 /* RH11/RP,RM drives */
#define INT_V_TU 9 /* RH11/TM03/TU45 */
#define INT_V_DZ 16 /* DZ11 */
#define INT_V_RP 6 /* RH11/RP,RM drives */
#define INT_V_TU 7 /* RH11/TM03/TU45 */
#define INT_V_DZ0RX 16 /* DZ11 */
#define INT_V_DZ0TX 17
#define INT_V_PTR 24 /* PC11 */
#define INT_V_PTP 25
#define INT_V_LP20 26 /* LPT20 */
#define INT_RP (1u << INT_V_RP)
#define INT_TU (1u << INT_V_TU)
#define INT_DZ (1u << INT_V_DZ)
#define INT_DZ0RX (1u << INT_V_DZ0RX)
#define INT_DZ0TX (1u << INT_V_DZ0TX)
#define INT_PTR (1u << INT_V_PTR)
#define INT_PTP (1u << INT_V_PTP)
#define INT_LP20 (1u << INT_V_LP20)
@ -613,14 +620,15 @@ typedef int64 d10; /* PDP-10 data (36b) */
#define INT_UB1 INT_RP /* on Unibus 1 */
#define INT_UB3 (0xFFFFFFFFu & ~INT_UB1) /* on Unibus 3 */
#define INT_IPL7 0x000000FF /* int level masks */
#define INT_IPL6 0x0000FF00
#define INT_IPL5 0x00FF0000
#define INT_IPL4 0x3F000000
#define INT_IPL7 0x0000000F /* int level masks */
#define INT_IPL6 0x000000F0
#define INT_IPL5 0x000FFF00
#define INT_IPL4 0x3FF00000
#define VEC_PTR 0070 /* interrupt vectors */
#define VEC_PTP 0074
#define VEC_TU 0224
#define VEC_RP 0254
#define VEC_DZ 0340
#define VEC_DZ0RX 0340
#define VEC_DZ0TX 0344
#define VEC_LP20 0754

View file

@ -25,6 +25,7 @@
uba Unibus adapters
1-Jun-01 RMS Updated DZ11 vectors
12-May-01 RMS Fixed typo
The KS10 uses the PDP-11 Unibus for its I/O, via adapters. While
@ -94,8 +95,8 @@ extern jmp_buf save_env;
extern d10 Read (a10 ea);
extern void pi_eval ();
extern t_stat dz_rd (int32 *data, int32 addr, int32 access);
extern t_stat dz_wr (int32 data, int32 addr, int32 access);
extern t_stat dz0_rd (int32 *data, int32 addr, int32 access);
extern t_stat dz0_wr (int32 data, int32 addr, int32 access);
extern t_stat pt_rd (int32 *data, int32 addr, int32 access);
extern t_stat pt_wr (int32 data, int32 addr, int32 access);
extern t_stat lp20_rd (int32 *data, int32 addr, int32 access);
@ -162,7 +163,7 @@ struct iolink iotable[] = {
{ IO_UBA3+IO_TMBASE, IO_UBA3+IO_TMBASE+033, 0,
&tu_rd, &tu_wr }, /* mag tape */
/* { IO_UBA3+IO_DZBASE, IO_UBA3+IO_DZBASE+07, INT_DZ,
&dz_rd, &dz_wr }, /* terminal mux */
&dz0_rd, &dz0_wr }, /* terminal mux */
{ IO_UBA3+IO_LPBASE, IO_UBA3+IO_LPBASE+017, 0,
&lp20_rd, &lp20_wr }, /* line printer */
{ IO_UBA3+IO_PTBASE, IO_UBA3+IO_PTBASE+07, INT_PTR,
@ -187,17 +188,17 @@ struct iolink iotable[] = {
/* Interrupt request to interrupt action map */
int32 (*int_ack[32])() = { /* int ack routines */
NULL, NULL, NULL, NULL, NULL, NULL, &rp_inta, &tu_inta,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
&rp_inta, &tu_inta, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, &lp20_inta, NULL, NULL, NULL, NULL, NULL };
/* Interrupt request to vector map */
int32 int_vec[32] = { /* int req to vector */
0, 0, 0, 0, 0, 0, VEC_RP, VEC_TU,
0, 0, 0, 0, 0, 0, 0, 0,
VEC_RP, VEC_TU, 0, 0, 0, 0, 0, 0,
VEC_DZ, 0, 0, 0, 0, 0, 0, 0,
VEC_DZ0RX, VEC_DZ0TX, 0, 0, 0, 0, 0, 0,
VEC_PTR, VEC_PTP, VEC_LP20, 0, 0, 0, 0, 0 };
/* IO 710 (DEC) TIOE - test I/O word, skip if zero

View file

@ -25,6 +25,7 @@
pag KS10 pager
19-May-01 RMS Added workaround for TOPS-20 V4.1 boot bug
03-May-01 RMS Fixed bug in indirect page table pointer processing
29-Apr-01 RMS Added CLRCSH for ITS, fixed LPMR
@ -659,6 +660,8 @@ return FALSE;
t_bool wrcstm (a10 ea, int32 prv)
{
cstm = Read (ea, prv);
if ((cpu_unit.flags & UNIT_T20V41) && (ea == 040127))
cstm = 0770000000000;
return FALSE;
}

View file

@ -335,21 +335,21 @@ t_stat rp_detach (UNIT *uptr);
*/
UNIT rp_unit[] = {
{ UDATA (&rp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_AUTO+
{ UDATA (&rp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
(RP06_DTYPE << UNIT_V_DTYPE), RP06_SIZE) },
{ UDATA (&rp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_AUTO+
{ UDATA (&rp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
(RP06_DTYPE << UNIT_V_DTYPE), RP06_SIZE) },
{ UDATA (&rp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_AUTO+
{ UDATA (&rp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
(RP06_DTYPE << UNIT_V_DTYPE), RP06_SIZE) },
{ UDATA (&rp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_AUTO+
{ UDATA (&rp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
(RP06_DTYPE << UNIT_V_DTYPE), RP06_SIZE) },
{ UDATA (&rp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_AUTO+
{ UDATA (&rp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
(RP06_DTYPE << UNIT_V_DTYPE), RP06_SIZE) },
{ UDATA (&rp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_AUTO+
{ UDATA (&rp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
(RP06_DTYPE << UNIT_V_DTYPE), RP06_SIZE) },
{ UDATA (&rp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_AUTO+
{ UDATA (&rp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
(RP06_DTYPE << UNIT_V_DTYPE), RP06_SIZE) },
{ UDATA (&rp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_AUTO+
{ UDATA (&rp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
(RP06_DTYPE << UNIT_V_DTYPE), RP06_SIZE) } };
REG rp_reg[] = {

View file

@ -23,6 +23,7 @@
be used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from Robert M Supnik.
27-May-01 RMS Added multiconsole support
29-Apr-01 RMS Fixed format for RDPCST, WRPCST
Added CLRCSH for ITS
03-Apr-01 RMS Added support for loading EXE files
@ -50,6 +51,7 @@ extern a10 saved_PC;
sim_PC pointer to saved PC register descriptor
sim_emax number of words for examine
sim_devices array of pointers to simulated devices
sim_consoles array of pointers to consoles (if more than one)
sim_stop_messages array of pointers to stop messages
sim_load binary loader
*/
@ -69,6 +71,8 @@ DEVICE *sim_devices[] = {
&rp_dev, &tu_dev,
NULL };
UNIT *sim_consoles = NULL;
const char *sim_stop_messages[] = {
"Unknown error",
"HALT instruction",

View file

@ -138,11 +138,11 @@
/* Condition code macros */
#define GET_BIT(ir,n) (((ir) >> n) & 1)
#define GET_SIGN_L(ir) GET_BIT((ir), 31)
#define GET_SIGN_W(ir) GET_BIT((ir), 15)
#define GET_SIGN_B(ir) GET_BIT((ir), 7)
#define GET_Z(ir) (ir == 0)
#define GET_BIT(ir,n) (((ir) >> n) & 1)
#define GET_SIGN_L(ir) GET_BIT((ir), 31)
#define GET_SIGN_W(ir) GET_BIT((ir), 15)
#define GET_SIGN_B(ir) GET_BIT((ir), 7)
#define GET_Z(ir) (ir == 0)
/* Decimal string structure */
@ -416,7 +416,7 @@ case 030: case 032: case 0130: case 0132:
Condition codes:
NZVC = set from src.lnt - dst.lnt
Registers (MOVC, MOVTC only)
Registers (MOVRC only)
R0 = max (0, src.len - dst.len)
R1:R3 = 0
R4:R5 = unchanged
@ -432,7 +432,7 @@ case 031: case 0131:
addr = A2ADR + A2LNT - mvlnt;
for (i = 0; i < mvlnt; i++) {
WriteB (movbuf[i], ((addr + i) & 0177777) | dsenable); }
fill = A3LNT & 0377; /* do fill, if any */
fill = A3LNT & 0377; /* do fill, if any */
for (i = mvlnt, j = 0; i < A2LNT; i++, j++) {
WriteB (fill, ((A2ADR + j) & 0177777) | dsenable); }
t = A1LNT - A2LNT; /* src.lnt - dst.lnt */
@ -509,7 +509,7 @@ case 042: case 043: case 0142: case 0143:
for (; R[0] != 0; R[0]--) { /* loop */
t = ReadB (R[1] | dsenable); /* get char as index */
c = ReadB (((A1ADR + t) & 0177777) | dsenable);
if (((c & mask) != 0) ^ (op & 1)) break; /* != + SCN, = + SPN? */
if (((c & mask) != 0) ^ (op & 1)) break; /* != + SCN, = + SPN? */
R[1] = (R[1] + 1) & 0177777; }
N = GET_SIGN_W (R[0]);
Z = GET_Z (R[0]);
@ -735,8 +735,7 @@ case 052: case 072: case 0152: case 0172:
ReadDstr (A2, &src2, op); /* get source2 */
N = Z = V = C = 0;
if (src1.sign != src2.sign) N = src1.sign;
else {
t = CmpDstr (&src1, &src2); /* compare strings */
else { t = CmpDstr (&src1, &src2); /* compare strings */
if (t < 0) N = 1;
else if (t == 0) Z = 1; }
if ((op & INLINE) == 0) /* if reg, clr reg */

View file

@ -25,6 +25,7 @@
cpu PDP-11 CPU (J-11 microprocessor)
01-Jun-01 RMS Added DZ11 support
23-Apr-01 RMS Added RK611 support
05-Apr-01 RMS Added TS11/TSV05 support
05-Mar-01 RMS Added clock calibration support
@ -325,7 +326,7 @@ struct iolink iotable[] = {
int32 int_vec[32] = { /* int req to vector */
0, 0, 0, VEC_PIRQ, VEC_CLK, VEC_DTA, 0, VEC_PIRQ,
VEC_RK, VEC_RL, VEC_RX, VEC_TM, VEC_RP, VEC_TS, VEC_HK, 0,
0, 0, 0, VEC_PIRQ, VEC_TTI, VEC_TTO, VEC_PTR, VEC_PTP,
VEC_DZ0RX, VEC_DZ0TX, 0, VEC_PIRQ, VEC_TTI, VEC_TTO, VEC_PTR, VEC_PTP,
VEC_LPT, 0, 0, 0, VEC_PIRQ, VEC_PIRQ, VEC_PIRQ, VEC_PIRQ };
int32 (*int_ack[32])() = { /* int ack routines */

View file

@ -26,6 +26,7 @@
The author gratefully acknowledges the help of Max Burnet, Megan Gentry,
and John Wilson in resolving questions about the PDP-11
01-Jun-01 RMS Added DZ11 support
23-Apr-01 RMS Added RK611 support
05-Apr-01 RMS Added TS11/TSV05 support
10-Feb-01 RMS Added DECtape support
@ -240,7 +241,7 @@ typedef struct fpac fpac_t;
<3:0> = BR7, <3> = PIR7
<7:4> = BR6, <7> = PIR6
<19:8> = BR5, <15> = PIR5
<19:8> = BR5, <19> = PIR5
<28:20> = BR4, <28> = PIR4
<29> = PIR3
<30> = PIR2
@ -258,6 +259,8 @@ typedef struct fpac fpac_t;
#define INT_V_RP 12
#define INT_V_TS 13
#define INT_V_HK 14
#define INT_V_DZ0RX 16
#define INT_V_DZ0TX 17
#define INT_V_PIR5 19
#define INT_V_TTI 20
#define INT_V_TTO 21
@ -280,6 +283,8 @@ typedef struct fpac fpac_t;
#define INT_RP (1u << INT_V_RP)
#define INT_TS (1u << INT_V_TS)
#define INT_HK (1u << INT_V_HK)
#define INT_DZ0RX (1u << INT_V_DZ0RX)
#define INT_DZ0TX (1u << INT_V_DZ0TX)
#define INT_PIR5 (1u << INT_V_PIR5)
#define INT_PTR (1u << INT_V_PTR)
#define INT_PTP (1u << INT_V_PTP)
@ -315,6 +320,8 @@ typedef struct fpac fpac_t;
#define VEC_TS 0224
#define VEC_RP 0254
#define VEC_RX 0264
#define VEC_DZ0RX 0310
#define VEC_DZ0TX 0314
/* CPU and FPU macros */

View file

@ -27,8 +27,8 @@
20-Apr-98 RMS Fixed bug in MODf integer truncation
17-Apr-98 RMS Fixed bug in STCfi range check
16-Apr-98 RMS Fixed bugs in STEXP, STCfi, round/pack
9-Apr-98 RMS Fixed bug in LDEXP
4-Apr-98 RMS Fixed bug in MODf condition codes
09-Apr-98 RMS Fixed bug in LDEXP
04-Apr-98 RMS Fixed bug in MODf condition codes
This module simulates the PDP-11 floating point unit (FP11 series).
It is called from the instruction decoder for opcodes 170000:177777.

View file

@ -28,7 +28,7 @@
26-Apr-01 RMS Added device enable/disable support
25-Mar-01 RMS Fixed block fill calculation
15-Feb-01 RMS Corrected bootstrap string
29-Jun-96 RMS Added unit disable support.
29-Jun-96 RMS Added unit disable support
The RK11 is an eight drive cartridge disk subsystem. An RK05 drive
consists of 203 cylinders, each with 2 surfaces containing 12 sectors

View file

@ -28,9 +28,9 @@
26-Apr-01 RMS Added device enable/disable support
25-Mar-01 RMS Fixed block fill calculation
15-Feb-01 RMS Corrected bootstrap string
12-Nov-97 RMS Added bad block table command.
25-Nov-96 RMS Default units to autosize.
29-Jun-96 RMS Added unit disable support.
12-Nov-97 RMS Added bad block table command
25-Nov-96 RMS Default units to autosize
29-Jun-96 RMS Added unit disable support
The RL11 is a four drive cartridge disk subsystem. An RL01 drive
consists of 256 cylinders, each with 2 surfaces containing 40 sectors

View file

@ -34,8 +34,8 @@
14-Apr-99 RMS Changed t_addr to unsigned
05-Oct-98 RMS Fixed bug, failing to interrupt on go error
04-Oct-98 RMS Changed names to allow coexistence with RH/TU77
12-Nov-97 RMS Added bad block table command.
10-Aug-97 RMS Fixed bugs in interrupt handling.
12-Nov-97 RMS Added bad block table command
10-Aug-97 RMS Fixed bugs in interrupt handling
The "Massbus style" disks consisted of several different large
capacity drives interfaced through a reasonably common (but not

View file

@ -23,16 +23,17 @@
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.
27-May-01 RMS Added multiconsole support
05-Apr-01 RMS Added support for TS11/TSV05
14-Mar-01 RMS Revised load/dump interface (again)
11-Feb-01 RMS Added DECtape support
30-Oct-00 RMS Added support for examine to file
14-Apr-99 RMS Changed t_addr to unsigned
09-Nov-98 RMS Fixed assignments of ROR/ROL (John Wilson).
27-Oct-98 RMS V2.4 load interface.
08-Oct-98 RMS Fixed bug in bad block routine.
30-Mar-98 RMS Fixed bug in floating point display.
12-Nov-97 RMS Added bad block table routine.
09-Nov-98 RMS Fixed assignments of ROR/ROL (John Wilson)
27-Oct-98 RMS V2.4 load interface
08-Oct-98 RMS Fixed bug in bad block routine
30-Mar-98 RMS Fixed bug in floating point display
12-Nov-97 RMS Added bad block table routine
*/
#include "pdp11_defs.h"
@ -58,6 +59,7 @@ extern int32 saved_PC;
sim_PC pointer to saved PC register descriptor
sim_emax number of words for examine
sim_devices array of pointers to simulated devices
sim_consoles array of pointers to consoles (if more than one)
sim_stop_messages array of pointers to stop messages
sim_load binary loader
*/
@ -79,6 +81,8 @@ DEVICE *sim_devices[] = {
&tm_dev, &ts_dev,
NULL };
UNIT *sim_consoles = NULL;
const char *sim_stop_messages[] = {
"Unknown error",
"Red stack trap",

View file

@ -25,6 +25,9 @@
cpu PDP-4/7/9/15 central processor
27-May-01 RMS Added second Teletype support, fixed bug in API
18-May-01 RMS Added PDP-9,-15 API option
16-May-01 RMS Fixed bugs in protection checks
26-Apr-01 RMS Added device enable/disable support
25-Jan-01 RMS Added DECtape support
18-Dec-00 RMS Added PDP-9,-15 memm init register
@ -46,7 +49,7 @@
all IORS I/O status register
PDP-7, PDP-9 EXTM extend mode
PDP-15 BANKM bank mode
PDP-7 TRAPM trap mode
PDP-7 USMD trap mode
PDP-9, PDP-15 USMD user mode
PDP-9, PDP-15 BR bounds register
PDP-15 XR index register
@ -241,22 +244,33 @@
#define save_ibkpt (cpu_unit.u3)
#define UNIT_V_NOEAE (UNIT_V_UF) /* EAE absent */
#define UNIT_NOEAE (1 << UNIT_V_NOEAE)
#define UNIT_V_MSIZE (UNIT_V_UF+1) /* dummy mask */
#define UNIT_V_NOAPI (UNIT_V_UF+1) /* API absent */
#define UNIT_NOAPI (1 << UNIT_V_NOAPI)
#define UNIT_V_MSIZE (UNIT_V_UF+2) /* dummy mask */
#define UNIT_MSIZE (1 << UNIT_V_MSIZE)
#if defined (PDP4)
#define EAE_DFLT UNIT_NOEAE
#else
#define EAE_DFLT 0
#endif
#if defined (PDP4) || (PDP7)
#define API_DFLT UNIT_NOAPI
#else
#define API_DFLT UNIT_NOAPI /* for now */
#endif
int32 M[MAXMEMSIZE] = { 0 }; /* memory */
int32 saved_LAC = 0; /* link'AC */
int32 saved_MQ = 0; /* MQ */
int32 saved_PC = 0; /* PC */
int32 int_req = 0; /* int requests */
int32 iors = 0; /* IORS */
int32 ion = 0; /* int on */
int32 ion_defer = 0; /* int defer */
int32 int_req = 0; /* int requests */
int32 api_enb = 0; /* API enable */
int32 api_req = 0; /* API requests */
int32 api_act = 0; /* API active */
int32 memm = 0; /* mem mode */
#if defined (PDP15)
int32 memm_init = 1; /* mem init */
@ -288,7 +302,31 @@ t_stat cpu_reset (DEVICE *dptr);
t_stat cpu_svc (UNIT *uptr);
t_stat cpu_set_size (UNIT *uptr, int32 value);
int32 upd_iors (void);
extern t_stat sim_activate (UNIT *uptr, int32 delay);
int32 api_eval (void);
static const int32 api_ffo[256] = {
8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
static const int32 api_vec[32] = {
0, 0, 0, 0, 0, 0, 0, 0,
0, ACH_TTO1, ACH_TTI1, ACH_CLK, 0, 0, 0, 0,
0, ACH_LPT, ACH_LPT, ACH_PTR, 0, 0, 0, ACH_RP,
ACH_RF, ACH_DRM, ACH_MTA, ACH_DTA, 0, 0, ACH_PWRFL, 0 };
/* CPU data structures
@ -298,7 +336,7 @@ extern t_stat sim_activate (UNIT *uptr, int32 delay);
cpu_mod CPU modifier list
*/
UNIT cpu_unit = { UDATA (&cpu_svc, UNIT_FIX + UNIT_BINK + EAE_DFLT,
UNIT cpu_unit = { UDATA (&cpu_svc, UNIT_FIX + UNIT_BINK + EAE_DFLT + API_DFLT,
MAXMEMSIZE) };
REG cpu_reg[] = {
@ -320,7 +358,11 @@ REG cpu_reg[] = {
{ FLDATA (TRAPP, trap_pending, 0) },
{ FLDATA (EXTM, memm, 0) },
{ FLDATA (EMIRP, emir_pending, 0) },
#elif defined (PDP9)
#endif
#if defined (PDP9)
{ FLDATA (APIENB, api_enb, 0) },
{ ORDATA (APIREQ, api_req, 8) },
{ ORDATA (APIACT, api_act, 8) },
{ ORDATA (BR, BR, ADDRSIZE) },
{ FLDATA (USMD, usmd, 0) },
{ FLDATA (USMDBUF, usmdbuf, 0) },
@ -332,7 +374,11 @@ REG cpu_reg[] = {
{ FLDATA (EMIRP, emir_pending, 0) },
{ FLDATA (RESTP, rest_pending, 0) },
{ FLDATA (PWRFL, int_req, INT_V_PWRFL) },
#elif defined (PDP15)
#endif
#if defined (PDP15)
{ FLDATA (APIENB, api_enb, 0) },
{ ORDATA (APIREQ, api_req, 8) },
{ ORDATA (APIACT, api_act, 8) },
{ ORDATA (XR, XR, 18) },
{ ORDATA (LR, LR, 18) },
{ ORDATA (BR, BR, ADDRSIZE) },
@ -349,6 +395,7 @@ REG cpu_reg[] = {
{ ORDATA (OLDPC, old_PC, ADDRSIZE), REG_RO },
{ FLDATA (STOP_INST, stop_inst, 0) },
{ FLDATA (NOEAE, cpu_unit.flags, UNIT_V_NOEAE), REG_HRO },
{ FLDATA (NOAPI, cpu_unit.flags, UNIT_V_NOAPI), REG_HRO },
{ DRDATA (XCT_MAX, xct_max, 8), PV_LEFT + REG_NZ },
{ ORDATA (BREAK, ibkpt_addr, ADDRSIZE + 1) },
{ ORDATA (WRU, sim_int_char, 8) },
@ -361,6 +408,10 @@ MTAB cpu_mod[] = {
{ UNIT_NOEAE, 0, "EAE", "EAE", NULL },
#else
{ UNIT_MSIZE, 4096, NULL, "4K", &cpu_set_size },
#endif
#if defined (PDP9) || defined (PDP15)
{ UNIT_NOAPI, UNIT_NOAPI, "no API", "NOAPI", NULL },
{ UNIT_NOAPI, 0, "API", "API", NULL },
#endif
{ UNIT_MSIZE, 8192, NULL, "8K", &cpu_set_size },
#if (MAXMEMSIZE > 8192)
@ -391,6 +442,7 @@ t_stat sim_instr (void)
{
extern int32 sim_interval;
register int32 PC, LAC, MQ;
int32 api_int, api_cycle, skp;
int32 iot_data, device, pulse;
t_stat reason;
extern UNIT clk_unit;
@ -422,94 +474,15 @@ extern int32 mt (int32 pulse, int32 AC);
extern int32 dt75 (int32 pulse, int32 AC);
extern int32 dt76 (int32 pulse, int32 AC);
#endif
#if defined (TTY1)
extern int32 tti1 (int32 pulse, int32 AC);
extern int32 tto1 (int32 pulse, int32 AC);
#endif
#define JMS_WORD(t) (((LAC & 01000000) >> 1) | ((memm & 1) << 16) | \
(((t) & 1) << 15) | ((PC) & 077777))
#define INCR_ADDR(x) (((x) & epcmask) | (((x) + 1) & damask))
#define SEXT(x) ((int) (((x) & 0400000)? (x) | ~0777777: (x) & 0777777))
/* Restore register state */
#if defined (PDP15)
register int32 epcmask, damask;
damask = memm? 017777: 07777; /* set dir addr mask */
epcmask = ADDRMASK & ~damask; /* extended PC mask */
#else
#define damask 017777 /* direct addr mask */
#define epcmask (ADDRMASK & ~damask) /* extended PC mask */
#endif
PC = saved_PC & ADDRMASK; /* load local copies */
LAC = saved_LAC & 01777777;
MQ = saved_MQ & 0777777;
reason = 0;
sim_rtc_init (clk_unit.wait); /* init calibration */
/* Main instruction fetch/decode loop: check trap and interrupt */
while (reason == 0) { /* loop until halted */
register int32 IR, MA, t, xct_count;
register int32 link_init, fill;
if (sim_interval <= 0) { /* check clock queue */
if (reason = sim_process_event ()) break; }
/* Protection traps work like interrupts, with these quirks:
PDP-7 extend mode forced on, M[0] = PC, PC = 2
PDP-9 extend mode ???, M[0/20] = PC, PC = 0/21
PDP-15 bank mode unchanged, M[0/20] = PC, PC = 0/21
*/
#if defined (PDP7)
if (trap_pending) { /* trap pending? */
old_PC = PC; /* save old PC */
M[0] = JMS_WORD (1); /* save state */
PC = 2; /* fetch next from 2 */
ion = 0; /* interrupts off */
memm = 1; /* extend on */
emir_pending = trap_pending = 0; /* emir, trap off */
usmd = 0; } /* protect off */
#elif defined (PDP9)
if (trap_pending) { /* trap pending? */
old_PC = PC; /* save old PC */
MA = ion? 0: 020; /* save in 0 or 20 */
M[MA] = JMS_WORD (1); /* save state */
PC = MA + 1; /* fetch next */
ion = 0; /* interrupts off */
/*??? memm = 0; /* extend off */
emir_pending = rest_pending = trap_pending = 0; /* emir,rest,trap off */
usmd = 0; } /* protect off */
#elif defined (PDP15)
if (trap_pending) { /* trap pending? */
old_PC = PC; /* save old PC */
MA = ion? 0: 020; /* save in 0 or 20 */
M[MA] = JMS_WORD (1); /* save state */
PC = MA + 1; /* fetch next */
ion = 0; /* interrupts off */
emir_pending = rest_pending = trap_pending = 0; /* emir,rest,trap off */
usmd = 0; } /* protect off */
#endif
if (ion && !ion_defer && int_req) { /* interrupt? */
old_PC = PC; /* save old PC */
M[0] = JMS_WORD (usmd); /* save state */
PC = 1; /* fetch next from 1 */
ion = 0; /* interrupts off */
#if !defined (PDP15) /* except PDP-15, */
memm = 0; /* extend off */
#endif
emir_pending = rest_pending = 0; /* emir, restore off */
usmd = 0; } /* protect off */
if (PC == ibkpt_addr) { /* breakpoint? */
save_ibkpt = ibkpt_addr; /* save ibkpt */
ibkpt_addr = ibkpt_addr | ILL_ADR_FLAG; /* disable */
sim_activate (&cpu_unit, 1); /* sched re-enable */
reason = STOP_IBKPT; /* stop simulation */
break; }
/* The following macros implement addressing. They account for autoincrement
addressing, extended addressing, and memory protection, if it exists.
@ -563,7 +536,7 @@ if (PC == ibkpt_addr) { /* breakpoint? */
if (!MEM_ADDR_OK (x)) { \
nexm = prvn = trap_pending = 1; \
break; } \
if ((x) >= BR) { \
if ((x) < BR) { \
prvn = trap_pending = 1; \
break; } } \
if (!MEM_ADDR_OK (x)) nexm = 1
@ -604,7 +577,7 @@ if (PC == ibkpt_addr) { /* breakpoint? */
if (!MEM_ADDR_OK (x)) { \
nexm = prvn = trap_pending = 1; \
break; } \
if ((x) >= BR) { \
if ((x) < BR) { \
prvn = trap_pending = 1; \
break; } } \
if (!MEM_ADDR_OK (x)) nexm = 1
@ -613,20 +586,133 @@ if (PC == ibkpt_addr) { /* breakpoint? */
if (!MEM_ADDR_OK (x)) break
#endif
/* Restore register state */
#if defined (PDP15)
register int32 epcmask, damask;
damask = memm? 017777: 07777; /* set dir addr mask */
epcmask = ADDRMASK & ~damask; /* extended PC mask */
#else
#define damask 017777 /* direct addr mask */
#define epcmask (ADDRMASK & ~damask) /* extended PC mask */
#endif
PC = saved_PC & ADDRMASK; /* load local copies */
LAC = saved_LAC & 01777777;
MQ = saved_MQ & 0777777;
reason = 0;
sim_rtc_init (clk_unit.wait); /* init calibration */
if (cpu_unit.flags & UNIT_NOAPI) api_enb = api_req = api_act = 0;
api_int = api_eval (); /* eval API */
api_cycle = 0; /* not API cycle */
/* Main instruction fetch/decode loop: check trap and interrupt */
while (reason == 0) { /* loop until halted */
register int32 IR, MA, t, xct_count;
register int32 link_init, fill;
if (sim_interval <= 0) { /* check clock queue */
if (reason = sim_process_event ()) break;
api_int = api_eval (); } /* eval API */
/* Protection traps work like interrupts, with these quirks:
PDP-7 extend mode forced on, M[0] = PC, PC = 2
PDP-9 extend mode ???, M[0/20] = PC, PC = 0/21
PDP-15 bank mode unchanged, M[0/20] = PC, PC = 0/21
*/
#if defined (PDP7)
if (trap_pending) { /* trap pending? */
old_PC = PC; /* save old PC */
M[0] = JMS_WORD (1); /* save state */
PC = 2; /* fetch next from 2 */
ion = 0; /* interrupts off */
memm = 1; /* extend on */
emir_pending = trap_pending = 0; /* emir, trap off */
usmd = 0; } /* protect off */
#endif
#if defined (PDP9) || defined (PDP15)
if (trap_pending) { /* trap pending? */
old_PC = PC; /* save old PC */
MA = ion? 0: 020; /* save in 0 or 20 */
M[MA] = JMS_WORD (1); /* save state */
PC = MA + 1; /* fetch next */
ion = 0; /* interrupts off */
emir_pending = rest_pending = trap_pending = 0; /* emir,rest,trap off */
usmd = 0; } /* protect off */
/* PDP-9 and PDP-15 automatic priority interrupt (API) */
if (api_int && !ion_defer) { /* API intr? */
int32 i, lvl = api_int - 1; /* get req level */
api_act = api_act | (0200 >> lvl); /* set level active */
if (lvl >= 4) { /* software req? */
MA = ACH_SWRE + lvl - 4; /* vec = 40:43 */
api_req = api_req & ~(0200 >> lvl); } /* remove request */
else { MA = 0; /* assume fails */
for (i = 31; i >= 0; i--) { /* loop hi to lo */
if ((int_req >> i) & 1) { /* int req set? */
MA = api_vec[i]; /* get vector */
break; } } } /* and stop */
if (MA == 0) { /* bad channel? */
reason = STOP_API; /* API error */
break; }
api_int = api_eval (); /* no API int */
api_cycle = 1; /* in API cycle */
emir_pending = rest_pending = 0; /* emir, restore off */
xct_count = 0;
goto xct_instr; }
/* Standard program interrupt */
if (!(api_enb && api_act) && ion && !ion_defer && int_req) {
#else
if (ion && !ion_defer && int_req) { /* interrupt? */
#endif
old_PC = PC; /* save old PC */
M[0] = JMS_WORD (usmd); /* save state */
PC = 1; /* fetch next from 1 */
ion = 0; /* interrupts off */
#if !defined (PDP15) /* except PDP-15, */
memm = 0; /* extend off */
#endif
emir_pending = rest_pending = 0; /* emir, restore off */
usmd = 0; } /* protect off */
/* Breakpoint */
if (PC == ibkpt_addr) { /* breakpoint? */
save_ibkpt = ibkpt_addr; /* save ibkpt */
ibkpt_addr = ibkpt_addr | ILL_ADR_FLAG; /* disable */
sim_activate (&cpu_unit, 1); /* sched re-enable */
reason = STOP_IBKPT; /* stop simulation */
break; }
/* Fetch, decode instruction */
MA = PC; /* fetch at PC */
CHECK_ADDR_R (MA); /* validate addr */
IR = M[MA]; /* fetch instruction */
PC = INCR_ADDR (PC); /* increment PC */
#if defined (PDP9) || defined (PDP15)
if (usmd) { /* user mode? */
if (!MEM_ADDR_OK (PC)) { /* nxm? */
nexm = prvn = trap_pending = 1; /* abort fetch */
continue; } \
if (PC < BR) { /* bounds viol? */
prvn = trap_pending = 1; /* abort fetch */
continue; } }
else if (!MEM_ADDR_OK (PC)) nexm = 1; /* flag nxm */
if (!ion_defer) usmd = usmdbuf; /* no IOT? load usmd */
#endif
if (ion_defer) ion_defer = ion_defer - 1; /* count down defer */
xct_count = 0; /* track nested XCT's */
sim_interval = sim_interval - 1;
MA = PC; /* fetch at PC */
PC = INCR_ADDR (PC); /* increment PC */
xct_instr: /* label for XCT */
IR = M[MA]; /* fetch instruction */
if (ion_defer) ion_defer = ion_defer - 1; /* count down defer */
if (sim_interval) sim_interval = sim_interval - 1;
MA = (MA & epcmask) | (IR & damask); /* effective address */
switch ((IR >> 13) & 037) { /* decode IR<0:4> */
@ -752,13 +838,13 @@ case 020: /* XCT, dir */
#if defined (PDP9)
ion_defer = 1; /* defer intr */
#endif
IR = M[MA]; /* get instruction */
goto xct_instr; /* go execute */
/* CAL: opcode 00
On the PDP-4 and PDP-7, CAL (I) is exactly the same as JMS (I) 20
On the PDP-9, CAL clears user mode
On the PDP-9 and PDP-15, CAL clears user mode
On the PDP-9 and PDP-15 with API, CAL activates level 4
On the PDP-15, CAL goes to absolute 20, regardless of mode
*/
@ -771,6 +857,9 @@ case 001: case 000: /* CAL */
#endif
#if defined (PDP9) || defined (PDP15)
usmd = 0; /* clear user mode */
if ((cpu_unit.flags & UNIT_NOAPI) == 0) { /* if API, act lvl 4 */
api_act = api_act | 010;
api_int = api_eval (); }
#endif
if (IR & 0020000) { INDIRECT; } /* indirect? */
CHECK_ADDR_W (MA);
@ -800,7 +889,7 @@ case 004: /* JMS, dir */
*/
case 031: /* JMP, indir */
CHECK_AUTO_INC; /* check auto inc */
CHECK_AUTO_INC; /* check auto inc */
#if defined (PDP7) || defined (PDP9)
if (emir_pending && (((M[MA] >> 16) & 1) == 0)) memm = 0;
#endif
@ -825,55 +914,56 @@ case 037: /* OPR, indir */
break;
case 036: /* OPR, dir */
skp = 0; /* assume no skip */
switch ((IR >> 6) & 017) { /* decode IR<8:11> */
case 0: /* nop */
break;
case 1: /* SMA */
if ((LAC & 0400000) != 0) PC = INCR_ADDR (PC);
if ((LAC & 0400000) != 0) skp = 1;
break;
case 2: /* SZA */
if ((LAC & 0777777) == 0) PC = INCR_ADDR (PC);
if ((LAC & 0777777) == 0) skp = 1;
break;
case 3: /* SZA | SMA */
if (((LAC & 0777777) == 0) || ((LAC & 0400000) != 0))
PC = INCR_ADDR (PC);
skp = 1;
break;
case 4: /* SNL */
if (LAC >= 01000000) PC = INCR_ADDR (PC);
if (LAC >= 01000000) skp = 1;
break;
case 5: /* SNL | SMA */
if (LAC >= 0400000) PC = INCR_ADDR (PC);
if (LAC >= 0400000) skp = 1;
break;
case 6: /* SNL | SZA */
if ((LAC >= 01000000) || (LAC == 0)) PC = INCR_ADDR (PC);
if ((LAC >= 01000000) || (LAC == 0)) skp = 1;
break;
case 7: /* SNL | SZA | SMA */
if ((LAC >= 0400000) || (LAC == 0)) PC = INCR_ADDR (PC);
if ((LAC >= 0400000) || (LAC == 0)) skp = 1;
break;
case 010: /* SKP */
PC = INCR_ADDR (PC);
skp = 1;
break;
case 011: /* SPA */
if ((LAC & 0400000) == 0) PC = INCR_ADDR (PC);
if ((LAC & 0400000) == 0) skp = 1;
break;
case 012: /* SNA */
if ((LAC & 0777777) != 0) PC = INCR_ADDR (PC);
if ((LAC & 0777777) != 0) skp = 1;
break;
case 013: /* SNA & SPA */
if (((LAC & 0777777) != 0) && ((LAC & 0400000) == 0))
PC = INCR_ADDR (PC);
skp = 1;
break;
case 014: /* SZL */
if (LAC < 01000000) PC = INCR_ADDR (PC);
if (LAC < 01000000) skp = 1;
break;
case 015: /* SZL & SPA */
if (LAC < 0400000) PC = INCR_ADDR (PC);
if (LAC < 0400000) skp = 1;
break;
case 016: /* SZL & SNA */
if ((LAC < 01000000) && (LAC != 0)) PC = INCR_ADDR (PC);
if ((LAC < 01000000) && (LAC != 0)) skp = 1;
break;
case 017: /* SZL & SNA & SPA */
if ((LAC < 0400000) && (LAC != 0)) PC = INCR_ADDR (PC);
if ((LAC < 0400000) && (LAC != 0)) skp = 1;
break; } /* end switch skips */
/* OPR, continued */
@ -968,6 +1058,7 @@ case 036: /* OPR, dir */
if (IR & 0000040) { /* HLT */
if (usmd) prvn = trap_pending = 1;
else reason = STOP_HALT; }
if (skp && !prvn) PC = INCR_ADDR (PC); /* if skip, inc PC */
break; /* end OPR */
/* EAE: opcode 64
@ -1169,7 +1260,11 @@ case 035: /* index operates */
703301 undefined TTS TTS TTS
703341 undefined SKP7 SKP7 SPCO
703302 undefined CAF CAF CAF
703304 undefined undefined DBK DBK
703344 undefined undefined DBR DBR
705501 undefined undefined SPI SPI
705502 undefined undefined RPL RPL
705504 undefined undefined ISA ISA
707701 undefined SEM SEM undefined
707741 undefined undefined undefined SKP15
707761 undefined undefined undefined SBA
@ -1203,10 +1298,11 @@ case 034: /* IOT */
else if (pulse == 042) ion = ion_defer = 1; /* ION */
else iot_data = clk (pulse, iot_data);
break;
#endif
/* PDP-7 system IOT's */
#elif defined (PDP7)
#if defined (PDP7)
switch (device) { /* decode IR<6:11> */
case 0: /* CPU and clock */
if (pulse == 002) ion = 0; /* IOF */
@ -1226,10 +1322,11 @@ case 034: /* IOT */
memm = emir_pending = 1; /* ext on, restore */
else if (pulse == 004) memm = 0; /* LEM */
break;
#endif
/* PDP-9 system IOT's */
/* PDP-9 and PDP-15 system IOT's */
#elif defined (PDP9)
#if defined (PDP9) || defined (PDP15)
ion_defer = 1; /* delay interrupts */
switch (device) { /* decode IR<6:11> */
case 000: /* CPU and clock */
@ -1242,7 +1339,7 @@ case 034: /* IOT */
else if ((pulse == 041) && nexm) PC = INCR_ADDR (PC);
else if (pulse == 002) prvn = 0;
else if (pulse == 042) usmdbuf = 1;
else if (pulse == 004) BR = LAC & 076000;
else if (pulse == 004) BR = LAC & BRMASK;
else if (pulse == 044) nexm = 0;
break;
case 032: /* power fail */
@ -1252,8 +1349,27 @@ case 034: /* IOT */
case 033: /* CPU control */
if ((pulse == 001) || (pulse == 041)) PC = INCR_ADDR (PC);
else if (pulse == 002) reset_all (0); /* CAF */
else if (pulse == 044) rest_pending = 1; /* DBR */
else if (pulse == 044) rest_pending = 1; /* DBR */
if (((cpu_unit.flags & UNIT_NOAPI) == 0) && (pulse & 004)) {
int32 t = api_ffo[api_act & 0377];
api_act = api_act & ~(0200 >> t); }
break;
case 055: /* API control */
if (cpu_unit.flags & UNIT_NOAPI) reason = stop_inst;
else if (pulse == 001) { /* SPI */
if (((LAC & SIGN) && api_enb) ||
((LAC & 0377) > api_act))
iot_data = iot_data | IOT_SKP; }
else if (pulse == 002) { /* RPL */
iot_data = iot_data | (api_enb << 17) |
(api_req << 8) | api_act; }
else if (pulse == 004) { /* ISA */
api_enb = (iot_data & SIGN)? 1: 0;
api_req = api_req | ((LAC >> 8) & 017);
api_act = api_act | (LAC & 0377); }
break;
#endif
#if defined (PDP9)
case 077: /* extended memory */
if ((pulse == 001) && memm) PC = INCR_ADDR (PC);
else if (pulse == 002) memm = 1; /* EEM */
@ -1261,34 +1377,8 @@ case 034: /* IOT */
memm = emir_pending = 1; /* ext on, restore */
else if (pulse == 004) memm = 0; /* LEM */
break;
/* PDP-15 system IOT's */
#elif defined (PDP15)
ion_defer = 1; /* delay interrupts */
switch (device) { /* decode IR<6:11> */
case 000: /* CPU and clock */
if (pulse == 002) ion = 0; /* IOF */
else if (pulse == 042) ion = 1; /* ION */
else iot_data = clk (pulse, iot_data);
break;
case 017: /* mem protection */
if ((pulse == 001) && prvn) PC = INCR_ADDR (PC);
else if ((pulse == 041) && nexm) PC = INCR_ADDR (PC);
else if (pulse == 002) prvn = 0;
else if (pulse == 042) usmdbuf = 1;
else if (pulse == 004) BR = LAC & 0377400;
else if (pulse == 044) nexm = 0;
break;
case 032: /* power fail */
if ((pulse == 001) && (int_req & INT_PWRFL))
PC = INCR_ADDR (PC);
break;
case 033: /* CPU control */
if ((pulse == 001) || (pulse == 041)) PC = INCR_ADDR (PC);
else if (pulse == 002) reset_all (0); /* CAF */
else if (pulse == 044) rest_pending = 1; /* DBR */
break;
#endif
#if defined (PDP15)
case 077: /* bank addressing */
if ((pulse == 041) || ((pulse == 061) && memm))
PC = INCR_ADDR (PC); /* SKP15, SBA */
@ -1315,6 +1405,14 @@ case 034: /* IOT */
case 4: /* TTO */
iot_data = tto (pulse, iot_data);
break;
#if defined (TTY1)
case 040: /* TTO1 */
iot_data = tto1 (pulse, iot_data);
break;
case 041: /* TTI1 */
iot_data = tti1 (pulse, iot_data);
break;
#endif
#if defined (DRM)
case 060: /* drum */
if (dev_enb & INT_DRM) iot_data = drm60 (pulse, iot_data);
@ -1377,8 +1475,13 @@ case 034: /* IOT */
LAC = LAC | (iot_data & 0777777);
if (iot_data & IOT_SKP) PC = INCR_ADDR (PC);
if (iot_data >= IOT_REASON) reason = iot_data >> IOT_V_REASON;
api_int = api_eval (); /* eval API */
break; /* end case IOT */
} /* end switch opcode */
if (api_cycle) { /* API cycle? */
api_cycle = 0; /* cycle over */
usmd = 0; /* exit user mode */
trap_pending = prvn = 0; } /* no priv viol */
} /* end while */
/* Simulation halted */
@ -1390,20 +1493,21 @@ iors = upd_iors (); /* get IORS */
return reason;
}
/* Reset routine */
/* Evaluate API */
t_stat cpu_reset (DEVICE *dptr)
int32 api_eval (void)
{
SC = 0;
eae_ac_sign = 0;
ion = ion_defer = 0;
int_req = int_req & ~INT_PWRFL;
BR = 0;
usmd = usmdbuf = 0;
memm = memm_init;
nexm = prvn = trap_pending = 0;
emir_pending = rest_pending = 0;
return cpu_svc (&cpu_unit);
int32 i, hi;
static const uint32 api_mask[4] = {
API_L0, API_L1, API_L2, API_L3 };
if (api_enb == 0) return 0; /* off? no req */
api_req = api_req & ~0360; /* clr req<0:3> */
for (i = 0; i < 4; i++) {
if (int_req & api_mask[i]) api_req = api_req | (0200 >> i); }
hi = api_ffo[api_req & 0377]; /* find hi req */
if (hi < api_ffo[api_act & 0377]) return (hi + 1);
return 0;
}
/* Process IORS instruction */
@ -1441,6 +1545,23 @@ return (ion? IOS_ION: 0) |
std_iors () | lpt_iors ();
}
/* Reset routine */
t_stat cpu_reset (DEVICE *dptr)
{
SC = 0;
eae_ac_sign = 0;
ion = ion_defer = 0;
int_req = int_req & ~INT_PWRFL;
api_enb = api_req = api_act = 0;
BR = 0;
usmd = usmdbuf = 0;
memm = memm_init;
nexm = prvn = trap_pending = 0;
emir_pending = rest_pending = 0;
return cpu_svc (&cpu_unit);
}
/* Memory examine */
t_stat cpu_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw)

View file

@ -23,6 +23,7 @@
be used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from Robert M Supnik.
27-May-01 RMS Added second Teletype support
21-Jan-01 RMS Added DECtape support
14-Apr-99 RMS Changed t_addr to unsigned
02-Jan-96 RMS Added fixed head and moving head disks
@ -54,21 +55,23 @@
Type 24 serial drum
PDP9 32K KE09A EAE KSR-33 Teletype
KG09B mem extension PC09A paper tape reader and punch
KP09A power detection integral real time clock
KX09A mem protection Type 647D/E line printer (sixbit)
RF09/RS09 fixed head disk
KF09A auto pri intr PC09A paper tape reader and punch
KG09B mem extension integral real time clock
KP09A power detection Type 647D/E line printer (sixbit)
KX09A mem protection RF09/RS09 fixed head disk
TC59 magnetic tape
TC02/TU55 DECtape
LT09A second Teletype
PDP15 128K KE15 EAE KSR-35 Teletype
KF15 power detection PC15 paper tape reader and punch
KM15 mem protection KW15 real time clock
??KT15 mem relocation LP15 line printer
RP15 disk pack
KA15 auto pri intr PC15 paper tape reader and punch
KF15 power detection KW15 real time clock
KM15 mem protection LP15 line printer
??KT15 mem relocation RP15 disk pack
RF15/RF09 fixed head disk
TC59D magnetic tape
TC15/TU56 DECtape
LT15 second Teletype
??Indicates not implemented. The PDP-4 manual refers to both an EAE
??and a memory extension control; there is no documentation on either.
@ -84,6 +87,7 @@
#define STOP_HALT 2 /* HALT */
#define STOP_IBKPT 3 /* breakpoint */
#define STOP_XCT 4 /* nested XCT's */
#define STOP_API 5 /* invalid API int */
/* Peripheral configuration */
@ -101,6 +105,8 @@
#define RF 0 /* fixed head disk */
#define MTA 0 /* magtape */
#define DTA 0 /* DECtape */
#define TTY1 0 /* second Teletype */
#define BRMASK 0076000 /* bounds mask */
#elif defined (PDP15)
#define ADDRSIZE 17
#define LP15 0 /* ASCII printer */
@ -108,6 +114,8 @@
#define RP 0 /* disk pack */
#define MTA 0 /* magtape */
#define DTA 0 /* DECtape */
#define TTY1 0 /* second Teletype */
#define BRMASK 0377400 /* bounds mask */
#endif
/* Memory */
@ -125,6 +133,7 @@
#define LINK (DMASK + 1) /* link */
#define LACMASK (LINK | DMASK) /* link + data */
#define SIGN 0400000 /* sign bit */
#define OP_JMS 0100000 /* JMS */
#define OP_JMP 0600000 /* JMP */
#define OP_HLT 0740040 /* HLT */
@ -144,19 +153,55 @@
If flag based, API is hard to implement; if API based, IORS requires
extra code for implementation. I've chosen an API based model.
API channel Device API priority Notes
00 software 4 4
01 software 5 5
02 software 6 6
03 software 7 7
04 TC02/TC15 1
05 TC59D 1
06 drum 1 PDP-9 only
07 disk 1 PDP-9 only
10 paper tape reader 2
11 real time clock 3
12 power fail 0
13 memory parity 0
14 display 2
15 card reader 2
16 line printer 2
17 A/D converter 0
20 interprocessor buffer 3
21 360 link 3 PDP-9 only
22 data phone 2 PDP-15 only
23 RF09/RF15 1
24 RP15 1 PDP-15 only
25 plotter 1 PDP-15 only
26 -
27 -
30 -
31 -
32 -
33 -
34 LT15 TTO 3 PDP-15 only
35 LT15 TTI 3 PDP-15 only
36 -
37 -
Interrupt system, priority is left to right.
<30:28> = priority 0
<27:20> = priority 1
<19:14> = priority 2
<13:10> = priority 3
<9:4> = PI only
<3> = priority 4 (software)
<2> = priority 5 (software)
<1> = priority 6 (software)
<0> = priority 7 (software)
<19:12> = priority 2
<11:8> = priority 3
<7:0> = PI only
*/
#define API_L0 0xF0000000
#define API_L1 0x0FF00000
#define API_L2 0x000FF000
#define API_L3 0x00000F00
#define INT_V_PWRFL 30 /* powerfail */
#define INT_V_DTA 27 /* DECtape */
#define INT_V_MTA 26 /* magtape */
@ -166,14 +211,12 @@
#define INT_V_PTR 19 /* paper tape reader */
#define INT_V_LPT 18 /* line printer */
#define INT_V_LPTSPC 17 /* line printer spc */
#define INT_V_CLK 13 /* clock */
#define INT_V_TTI 9 /* keyboard */
#define INT_V_TTO 8 /* terminal */
#define INT_V_PTP 7 /* paper tape punch */
#define INT_V_SW4 3 /* software 4 */
#define INT_V_SW5 2 /* software 5 */
#define INT_V_SW6 1 /* software 6 */
#define INT_V_SW7 0 /* software 7 */
#define INT_V_CLK 11 /* clock */
#define INT_V_TTI1 10 /* LT15 keyboard */
#define INT_V_TTO1 9 /* LT15 output */
#define INT_V_TTI 7 /* console keyboard */
#define INT_V_TTO 6 /* console output */
#define INT_V_PTP 5 /* paper tape punch */
#define INT_PWRFL (1 << INT_V_PWRFL)
#define INT_DTA (1 << INT_V_DTA)
@ -185,13 +228,24 @@
#define INT_LPT (1 << INT_V_LPT)
#define INT_LPTSPC (1 << INT_V_LPTSPC)
#define INT_CLK (1 << INT_V_CLK)
#define INT_TTI1 (1 << INT_V_TTI1)
#define INT_TTO1 (1 << INT_V_TTO1)
#define INT_TTI (1 << INT_V_TTI)
#define INT_TTO (1 << INT_V_TTO)
#define INT_PTP (1 << INT_V_PTP)
#define INT_SW4 (1 << INT_V_SW4)
#define INT_SW5 (1 << INT_V_SW5)
#define INT_SW6 (1 << INT_V_SW6)
#define INT_SW7 (1 << INT_V_SW7)
#define ACH_SWRE 040 /* API channels */
#define ACH_PWRFL 052
#define ACH_DTA 044
#define ACH_MTA 045
#define ACH_DRM 046
#define ACH_RF 063
#define ACH_RP 064
#define ACH_PTR 050
#define ACH_LPT 056
#define ACH_CLK 051
#define ACH_TTI1 075
#define ACH_TTO1 074
/* I/O status flags for the IORS instruction

View file

@ -26,6 +26,7 @@
drm (PDP-7) Type 24 serial drum
(PDP-9) RM09 serial drum
10-Jun-01 RMS Cleaned up IOT decoding to reflect hardware
26-Apr-01 RMS Added device enable/disable support
14-Apr-99 RMS Changed t_addr to unsigned
*/
@ -108,14 +109,13 @@ int32 drm61 (int32 pulse, int32 AC)
{
int32 t;
if (pulse == 001) return (int_req & INT_DRM)? IOT_SKP + AC: AC; /* DRSF */
if (pulse == 002) { /* DRCF */
if (pulse & 001) { /* DRSF */
if (int_req & INT_DRM) AC = AC | IOT_SKP; }
if (pulse & 002) { /* DRCF */
int_req = int_req & ~INT_DRM; /* clear done */
drm_err = 0; } /* clear error */
if (pulse == 006) { /* DRSS */
if (pulse & 004) { /* DRSS */
drm_da = AC & DRM_SMASK; /* load sector # */
int_req = int_req & ~INT_DRM; /* clear done */
drm_err = 0; /* clear error */
t = ((drm_da % DRM_NUMSC) * DRM_NUMWDS) - GET_POS (drm_time);
if (t < 0) t = t + DRM_NUMWDT; /* wrap around? */
sim_activate (&drm_unit, t * drm_time); } /* schedule op */
@ -126,8 +126,9 @@ int32 drm62 (int32 pulse, int32 AC)
{
int32 t;
if (pulse == 001) return (drm_err)? AC: IOT_SKP + AC; /* DRSN */
if (pulse == 004) { /* DRCS */
if (pulse & 001) { /* DRSN */
if (drm_err == 0) AC = AC | IOT_SKP; }
if (pulse & 004) { /* DRCS */
int_req = int_req & ~INT_DRM; /* clear done */
drm_err = 0; /* clear error */
t = ((drm_da % DRM_NUMSC) * DRM_NUMWDS) - GET_POS (drm_time);

View file

@ -187,7 +187,7 @@ if (pulse == 042) { /* DSCD */
if (RF_BUSY) rf_sta = rf_sta | RFS_PGE; /* busy inhibits */
else rf_sta = 0;
rf_updsta (0); }
if (pulse == 0062) { /* DSRS */
if (pulse == 062) { /* DSRS */
if (RF_BUSY) rf_sta = rf_sta | RFS_PGE; /* busy sets PGE */
return rf_updsta (0); }
return AC;

View file

@ -29,6 +29,8 @@
tto teleprinter
clk clock
10-Jun-01 RMS Cleaned up IOT decoding to reflect hardware
27-May-01 RMS Added multiconsole support
10-Mar-01 RMS Added funny format loader support
05-Mar-01 RMS Added clock calibration support
22-Dec-00 RMS Added PDP-9/15 half duplex support
@ -50,6 +52,10 @@ int32 ptp_err = 0, ptp_stopioe = 0;
int32 tti_state = 0;
int32 tto_state = 0;
int32 clk_tps = 60;
#if defined (TTY1)
static uint8 tto_consout[CONS_SIZE];
#endif
t_stat clk_svc (UNIT *uptr);
t_stat ptr_svc (UNIT *uptr);
t_stat ptp_svc (UNIT *uptr);
@ -195,9 +201,9 @@ static const int32 tti_trans[128] = {
#define UNIT_HDX (1 << UNIT_V_HDX)
#if defined (PDP4) || defined (PDP7)
UNIT tti_unit = { UDATA (&tti_svc, UNIT_UC, 0), KBD_POLL_WAIT };
UNIT tti_unit = { UDATA (&tti_svc, UNIT_UC+UNIT_CONS, 0), KBD_POLL_WAIT };
#else
UNIT tti_unit = { UDATA (&tti_svc, UNIT_UC + UNIT_HDX, 0), KBD_POLL_WAIT };
UNIT tti_unit = { UDATA (&tti_svc, UNIT_UC+UNIT_HDX+UNIT_CONS, 0), KBD_POLL_WAIT };
#endif
REG tti_reg[] = {
@ -212,9 +218,16 @@ REG tti_reg[] = {
#endif
{ DRDATA (POS, tti_unit.pos, 31), PV_LEFT },
{ DRDATA (TIME, tti_unit.wait, 24), REG_NZ + PV_LEFT },
#if defined (TTY1)
{ FLDATA (CFLAG, tti_unit.flags, UNIT_V_CONS), REG_HRO },
#endif
{ NULL } };
MTAB tti_mod[] = {
#if defined (TTY1)
{ UNIT_CONS, 0, "inactive", NULL, NULL },
{ UNIT_CONS, UNIT_CONS, "active console", "CONSOLE", &set_console },
#endif
#if !defined (KSR28)
{ UNIT_UC, 0, "lower case", "LC", NULL },
{ UNIT_UC, UNIT_UC, "upper case", "UC", NULL },
@ -257,7 +270,7 @@ static const char tto_trans[64] = {
#define TTO_MASK ((1 << TTO_WIDTH) - 1)
UNIT tto_unit = { UDATA (&tto_svc, 0, 0), SERIAL_OUT_WAIT };
UNIT tto_unit = { UDATA (&tto_svc, UNIT_UC+UNIT_CONS, 0), SERIAL_OUT_WAIT };
REG tto_reg[] = {
{ ORDATA (BUF, tto_unit.buf, TTO_WIDTH) },
@ -268,10 +281,25 @@ REG tto_reg[] = {
#endif
{ DRDATA (POS, tto_unit.pos, 31), PV_LEFT },
{ DRDATA (TIME, tto_unit.wait, 24), PV_LEFT },
#if defined (TTY1)
{ BRDATA (CONSOUT, tto_consout, 8, 8, CONS_SIZE), REG_HIDDEN },
{ FLDATA (CFLAG, tto_unit.flags, UNIT_V_CONS), REG_HRO },
#endif
{ NULL } };
MTAB tto_mod[] = {
#if defined (TTY1)
{ UNIT_CONS, 0, "inactive", NULL, NULL },
{ UNIT_CONS, UNIT_CONS, "active console", "CONSOLE", &set_console },
#endif
#if !defined (KSR28)
{ UNIT_UC, 0, "lower case", "LC", NULL },
{ UNIT_UC, UNIT_UC, "upper case", "UC", NULL },
#endif
{ 0 } };
DEVICE tto_dev = {
"TTO", &tto_unit, tto_reg, NULL,
"TTO", &tto_unit, tto_reg, tto_mod,
1, 10, 31, 1, 8, 8,
NULL, NULL, &tto_reset,
NULL, NULL, NULL };
@ -280,14 +308,16 @@ DEVICE tto_dev = {
int32 clk (int32 pulse, int32 AC)
{
if (pulse == 001) return (int_req & INT_CLK)? IOT_SKP + AC: AC; /* CLSF */
if (pulse == 004) clk_reset (&clk_dev); /* CLOF */
else if (pulse == 044) { /* CLON */
int_req = int_req & ~INT_CLK; /* clear flag */
clk_state = 1; /* clock on */
if (!sim_is_active (&clk_unit)) /* already on? */
sim_activate (&clk_unit, /* start */
sim_rtc_init (clk_unit.wait)); } /* init calibr */
if (pulse & 001) { /* CLSF */
if (int_req & INT_CLK) AC = AC | IOT_SKP; }
if (pulse & 004) { /* CLON/CLOF */
if (pulse & 040) { /* CLON */
int_req = int_req & ~INT_CLK; /* clear flag */
clk_state = 1; /* clock on */
if (!sim_is_active (&clk_unit)) /* already on? */
sim_activate (&clk_unit, /* start, calibr */
sim_rtc_init (clk_unit.wait)); }
else clk_reset (&clk_dev); } /* CLOF */
return AC;
}
@ -335,10 +365,11 @@ return ((int_req & INT_CLK)? IOS_CLK: 0) |
int32 ptr (int32 pulse, int32 AC)
{
if (pulse == 001) return (int_req & INT_PTR)? IOT_SKP + AC: AC; /* RSF */
if (pulse & 001) { /* RSF */
if (int_req & INT_PTR) AC = AC | IOT_SKP; }
if (pulse & 002) { /* RRB, RCF */
int_req = int_req & ~INT_PTR; /* clear done */
AC = ptr_unit.buf; } /* return buffer */
AC = AC | ptr_unit.buf; } /* return buffer */
if (pulse & 004) { /* RSA, RSB */
ptr_state = (pulse & 040)? 18: 0; /* set mode */
int_req = int_req & ~INT_PTR; /* clear done */
@ -587,7 +618,8 @@ return SCPE_ARG;
int32 ptp (int32 pulse, int32 AC)
{
if (pulse == 001) return (int_req & INT_PTP)? IOT_SKP + AC: AC; /* PSF */
if (pulse & 001) { /* PSF */
if (int_req & INT_PTP) AC = AC | IOT_SKP; }
if (pulse & 002) int_req = int_req & ~INT_PTP; /* PCF */
if (pulse & 004) { /* PSA, PSB, PLS */
int_req = int_req & ~INT_PTP; /* clear flag */
@ -648,10 +680,11 @@ return detach_unit (uptr);
int32 tti (int32 pulse, int32 AC)
{
if (pulse == 001) return (int_req & INT_TTI)? IOT_SKP + AC: AC; /* KSF */
if (pulse == 002) { /* KRB */
if (pulse & 001) { /* KSF */
if (int_req & INT_TTI) AC = AC | IOT_SKP; }
if (pulse & 002) { /* KRB */
int_req = int_req & ~INT_TTI; /* clear flag */
return tti_unit.buf & TTI_MASK; } /* return buffer */
AC = AC | tti_unit.buf & TTI_MASK; } /* return buffer */
return AC;
}
@ -679,7 +712,11 @@ else { if ((temp = sim_poll_kbd ()) < SCPE_KFLAG) return temp;
if ((temp = sim_poll_kbd ()) < SCPE_KFLAG) return temp; /* no char or error? */
temp = temp & 0177;
if ((tti_unit.flags & UNIT_UC) && islower (temp)) temp = toupper (temp);
if (tti_unit.flags & UNIT_HDX) sim_putchar (temp);
if ((tti_unit.flags & UNIT_HDX) &&
(!(tto_unit.flags & UNIT_UC) ||
((temp >= 007) && (temp <= 0137)))) {
sim_putcons (temp, uptr);
tto_unit.pos = tto_unit.pos + 1; }
tti_unit.buf = temp | 0200; /* got char */
#endif
int_req = int_req | INT_TTI; /* set flag */
@ -694,6 +731,9 @@ t_stat tti_reset (DEVICE *dptr)
tti_unit.buf = 0; /* clear buffer */
tti_state = 0; /* clear state */
int_req = int_req & ~INT_TTI; /* clear flag */
#if defined (TTY1)
if (tti_unit.flags & UNIT_CONS) /* if active cons */
#endif
sim_activate (&tti_unit, tti_unit.wait); /* activate unit */
return SCPE_OK;
}
@ -702,7 +742,8 @@ return SCPE_OK;
int32 tto (int32 pulse, int32 AC)
{
if (pulse == 001) return (int_req & INT_TTO)? IOT_SKP + AC: AC; /* TSF */
if (pulse & 001) { /* TSF */
if (int_req & INT_TTO) AC = AC | IOT_SKP; }
if (pulse & 002) int_req = int_req & ~INT_TTO; /* clear flag */
if (pulse & 004) { /* load buffer */
sim_activate (&tto_unit, tto_unit.wait); /* activate unit */
@ -728,8 +769,11 @@ out = tto_trans[tto_unit.buf + tto_state]; /* translate */
#else
out = tto_unit.buf & 0177; /* ASCII... */
#endif
if ((temp = sim_putchar (out)) != SCPE_OK) return temp;
tto_unit.pos = tto_unit.pos + 1;
if (!(tto_unit.flags & UNIT_UC) ||
((out >= 007) && (out <= 0137))) {
temp = sim_putcons (out, uptr);
if (temp != SCPE_OK) return temp;
tto_unit.pos = tto_unit.pos + 1; }
return SCPE_OK;
}
@ -741,5 +785,8 @@ tto_unit.buf = 0; /* clear buffer */
tto_state = 0; /* clear state */
int_req = int_req & ~INT_TTO; /* clear flag */
sim_cancel (&tto_unit); /* deactivate unit */
#if defined (TTY1)
tto_unit.filebuf = tto_consout;
#endif
return SCPE_OK;
}

View file

@ -23,6 +23,8 @@
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.
27-May-01 RMS Added second Teletype support
18-May-01 RMS Added PDP-9,-15 API IOT's
12-May-01 RMS Fixed bug in RIM loaders
14-Mar-01 RMS Added extension detection of RIM format tapes
21-Jan-01 RMS Added DECtape support
@ -39,6 +41,7 @@
extern DEVICE cpu_dev;
extern DEVICE ptr_dev, ptp_dev;
extern DEVICE tti_dev, tto_dev;
extern UNIT tti_unit, tto_unit;
extern DEVICE clk_dev;
extern DEVICE lpt_dev;
#if defined (DRM)
@ -56,6 +59,10 @@ extern DEVICE mt_dev;
#if defined (DTA)
extern DEVICE dt_dev;
#endif
#if defined (TTY1)
extern DEVICE tti1_dev, tto1_dev;
extern UNIT tti1_unit, tto1_unit;
#endif
extern UNIT cpu_unit;
extern REG cpu_reg[];
extern int32 M[];
@ -87,7 +94,8 @@ REG *sim_PC = &cpu_reg[0];
int32 sim_emax = 3;
DEVICE *sim_devices[] = { &cpu_dev,
&ptr_dev, &ptp_dev, &tti_dev, &tto_dev,
&ptr_dev, &ptp_dev,
&tti_dev, &tto_dev,
&clk_dev, &lpt_dev,
#if defined (DRM)
&drm_dev,
@ -103,15 +111,28 @@ DEVICE *sim_devices[] = { &cpu_dev,
#endif
#if defined (MTA)
&mt_dev,
#endif
#if defined (TTY1)
&tti1_dev, &tto1_dev,
#endif
NULL };
#if defined (TTY1)
UNIT *sim_consoles[] = {
&tti_unit, &tto_unit,
&tti1_unit, &tto1_unit,
NULL };
#else
UNIT *sim_consoles = NULL;
#endif
const char *sim_stop_messages[] = {
"Unknown error",
"Undefined instruction",
"HALT instruction",
"Breakpoint",
"Nested XCT's" };
"Nested XCT's",
"Invalid API interrupt" };
/* Binary loader */
@ -279,7 +300,7 @@ static const char *opcode[] = {
"XCT", "ISZ", "AND", "SAD",
"JMP",
#if defined (PDP15) /* mem ref ind */
#if defined (PDP9) || defined (PDP15) /* mem ref ind */
"CAL*", "DAC*", "JMS*", "DZM*", /* normal */
"LAC*", "XOR*", "ADD*", "TAD*",
"XCT*", "ISZ*", "AND*", "SAD*",
@ -346,26 +367,34 @@ static const char *opcode[] = {
"MTTR", "MTCR", "MTSF", "MTRC", "MTAF",
"MTRS", "MTGO", "MTCM", "MTLC",
#endif
#if defined (DTA)
#if defined (DTA) /* TC02/TC15 */
"DTCA", "DTRA", "DTXA", "DTLA",
"DTEF", "DTRB", "DTDF",
#endif
#if defined (TTY1)
"KSF1", "KRB1",
"TSF1", "TCF1", "TLS1", "TCF1!TLS1",
#endif
#if defined (PDP7)
"ITON", "TTS", "SKP7", "CAF",
"SEM", "EEM", "EMIR", "LEM",
#elif defined (PDP9)
"PFSF", "TTS", "SKP7", "CAF",
"DBR", "SEM", "EEM", "LEM",
"MPSK", "MPSNE", "MPCV", "MPEU",
"MPLD", "MPCNE",
#endif
#if defined (PDP9)
"SKP7", "SEM", "EEM", "LEM",
"LPDI", "LPEI",
#elif defined (PDP15)
"PFSF", "TTS", "SPCO", "CAF",
"DBR", "SKP15", "RES",
#endif
#if defined (PDP15)
"SPCO", "SKP15", "RES",
"SBA", "DBA", "EBA",
"AAS", "PAX", "PAL", "AAC",
"PXA", "AXS", "PXL", "PLA",
"PLX", "CLAC","CLX", "CLLR", "AXR",
#endif
#if defined (PDP9) || defined (PDP15)
"MPSK", "MPSNE", "MPCV", "MPEU",
"MPLD", "MPCNE", "PFSF",
"TTS", "CAF", "DBK", "DBR",
"SPI", "RPL", "ISA",
#endif
"IOT", /* general */
@ -493,22 +522,30 @@ static const int32 opc_val[] = {
0707541+I_NPI, 0707552+I_NPN, 0707544+I_NPI, 0707545+I_NPI,
0707561+I_NPI, 0707572+I_NPN, 0707601+I_NPI,
#endif
#if defined (TTY1)
0704101+I_NPI, 0704112+I_NPN,
0704001+I_NPI, 0704002+I_NPI, 0704004+I_NPI, 0704006+I_NPI,
#endif
#if defined (PDP7)
0703201+I_NPI, 0703301+I_NPI, 0703341+I_NPI, 0703302+I_NPI,
0707701+I_NPI, 0707702+I_NPI, 0707742+I_NPI, 0707704+I_NPI,
#elif defined (PDP9)
0700062+I_NPI, 0703301+I_NPI, 0703341+I_NPI, 0703302+I_NPI,
0703344+I_NPI, 0707701+I_NPI, 0707702+I_NPI, 0707704+I_NPI,
0701701+I_NPI, 0701741+I_NPI, 0701702+I_NPI, 0701742+I_NPI,
0701704+I_NPI, 0701644+I_NPI,
#endif
#if defined (PDP9)
0703341+I_NPI, 0707701+I_NPI, 0707702+I_NPI, 0707704+I_NPI,
0706504+I_NPI, 0706604+I_NPI,
#elif defined (PDP15)
0700062+I_NPI, 0703301+I_NPI, 0703341+I_NPI, 0703302+I_NPI,
0703344+I_NPI, 0707741+I_NPI, 0707742+I_NPI,
#endif
#if defined (PDP15)
0703341+I_NPI, 0707741+I_NPI, 0707742+I_NPI,
0707761+I_NPI, 0707762+I_NPI, 0707764+I_NPI,
0720000+I_XR9, 0721000+I_XR, 0722000+I_XR, 0723000+I_XR9,
0724000+I_XR, 0725000+I_XR9, 0726000+I_XR, 0730000+I_XR,
0731000+I_XR, 0734000+I_XR, 0735000+I_XR, 0736000+I_XR, 0737000+I_XR9,
#endif
#if defined (PDP9) || defined (PDP15)
0701701+I_NPI, 0701741+I_NPI, 0701702+I_NPI, 0701742+I_NPI,
0701704+I_NPI, 0701744+I_NPI, 0703201+I_NPI,
0703301+I_NPI, 0703302+I_NPI, 0703304+I_NPI, 0703344+I_NPI,
0705501+I_NPI, 0705512+I_NPN, 0705504+I_NPI,
#endif
0700000+I_IOT,
@ -785,6 +822,8 @@ case I_V_MRF: /* mem ref */
#else
dmask = 017777;
cptr = get_glyph (cptr, gbuf, 0); /* get next field */
#endif
#if defined (PDP4) || defined (PDP7)
if (strcmp (gbuf, "I") == 0) { /* indirect? */
val[0] = val[0] | 020000;
cptr = get_glyph (cptr, gbuf, 0); }

190
pdp18b_tt1.c Normal file
View file

@ -0,0 +1,190 @@
/* pdp18b_tt1.c: 18b PDP's second Teletype
Copyright (c) 1993-2001, Robert M Supnik
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Except as contained in this notice, the name of 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.
tti1 keyboard
tto1 teleprinter
10-Jun-01 RMS Cleaned up IOT decoding to reflect hardware
*/
#include "pdp18b_defs.h"
#include <ctype.h>
#define UNIT_V_UC (UNIT_V_UF + 0) /* UC only */
#define UNIT_UC (1 << UNIT_V_UC)
extern int32 int_req, saved_PC;
t_stat tti1_svc (UNIT *uptr);
t_stat tto1_svc (UNIT *uptr);
t_stat tti1_reset (DEVICE *dptr);
t_stat tto1_reset (DEVICE *dptr);
extern t_stat sim_poll_kbd (void);
extern t_stat sim_putchar (int32 out);
static uint8 tto1_consout[CONS_SIZE];
/* TTI1 data structures
tti1_dev TTI1 device descriptor
tti1_unit TTI1 unit
tto1_mod TTI1 modifier list
tti1_reg TTI1 register list
*/
UNIT tti1_unit = { UDATA (&tti1_svc, UNIT_UC, 0), KBD_POLL_WAIT };
REG tti1_reg[] = {
{ ORDATA (BUF, tti1_unit.buf, 8) },
{ FLDATA (INT, int_req, INT_V_TTI1) },
{ FLDATA (DONE, int_req, INT_V_TTI1) },
{ FLDATA (UC, tti1_unit.flags, UNIT_V_UC), REG_HRO },
{ DRDATA (POS, tti1_unit.pos, 31), PV_LEFT },
{ DRDATA (TIME, tti1_unit.wait, 24), REG_NZ + PV_LEFT },
{ FLDATA (CFLAG, tti1_unit.flags, UNIT_V_CONS), REG_HRO },
{ NULL } };
MTAB tti1_mod[] = {
{ UNIT_CONS, 0, "inactive", NULL, NULL },
{ UNIT_CONS, UNIT_CONS, "active console", "CONSOLE", &set_console },
{ UNIT_UC, 0, "lower case", "LC", NULL },
{ UNIT_UC, UNIT_UC, "upper case", "UC", NULL },
{ 0 } };
DEVICE tti1_dev = {
"TTI1", &tti1_unit, tti1_reg, tti1_mod,
1, 10, 31, 1, 8, 8,
NULL, NULL, &tti1_reset,
NULL, NULL, NULL };
/* TTO1 data structures
tto1_dev TTO1 device descriptor
tto1_unit TTO1 unit
tto1_mod TTO1 modifier list
tto1_reg TTO1 register list
*/
UNIT tto1_unit = { UDATA (&tto1_svc, UNIT_UC, 0), SERIAL_OUT_WAIT };
REG tto1_reg[] = {
{ ORDATA (BUF, tto1_unit.buf, 8) },
{ FLDATA (INT, int_req, INT_V_TTO1) },
{ FLDATA (DONE, int_req, INT_V_TTO1) },
{ DRDATA (POS, tto1_unit.pos, 31), PV_LEFT },
{ DRDATA (TIME, tto1_unit.wait, 24), PV_LEFT },
{ BRDATA (CONSOUT, tto1_consout, 8, 8, CONS_SIZE), REG_HIDDEN },
{ FLDATA (CFLAG, tto1_unit.flags, UNIT_V_CONS), REG_HRO },
{ NULL } };
MTAB tto1_mod[] = {
{ UNIT_CONS, 0, "inactive", NULL, NULL },
{ UNIT_CONS, UNIT_CONS, "active console", "CONSOLE", &set_console },
{ UNIT_UC, 0, "lower case", "LC", NULL },
{ UNIT_UC, UNIT_UC, "upper case", "UC", NULL },
{ 0 } };
DEVICE tto1_dev = {
"TTO1", &tto1_unit, tto1_reg, tto1_mod,
1, 10, 31, 1, 8, 8,
NULL, NULL, &tto1_reset,
NULL, NULL, NULL };
/* Terminal input: IOT routine */
int32 tti1 (int32 pulse, int32 AC)
{
if (pulse & 001) { /* KSF1 */
if (int_req & INT_TTI1) AC = AC | IOT_SKP; }
if (pulse & 002) { /* KRB1 */
int_req = int_req & ~INT_TTI1; /* clear flag */
AC= AC | tti1_unit.buf; } /* return buffer */
return AC;
}
/* Unit service */
t_stat tti1_svc (UNIT *uptr)
{
int32 temp;
sim_activate (&tti1_unit, tti1_unit.wait); /* continue poll */
if ((temp = sim_poll_kbd ()) < SCPE_KFLAG) return temp; /* no char or error? */
temp = temp & 0177;
if ((tti1_unit.flags & UNIT_UC) && islower (temp)) temp = toupper (temp);
tti1_unit.buf = temp | 0200; /* got char */
int_req = int_req | INT_TTI1; /* set flag */
tti1_unit.pos = tti1_unit.pos + 1;
return SCPE_OK;
}
/* Reset routine */
t_stat tti1_reset (DEVICE *dptr)
{
tti1_unit.buf = 0; /* clear buffer */
int_req = int_req & ~INT_TTI; /* clear flag */
if (tti1_unit.flags & UNIT_CONS) /* if active console */
sim_activate (&tti1_unit, tti1_unit.wait); /* activate unit */
return SCPE_OK;
}
/* Terminal output: IOT routine */
int32 tto1 (int32 pulse, int32 AC)
{
if (pulse & 001) { /* TSF */
if (int_req & INT_TTO1) AC = AC | IOT_SKP; }
if (pulse & 002) int_req = int_req & ~INT_TTO1; /* clear flag */
if (pulse & 004) { /* load buffer */
sim_activate (&tto1_unit, tto1_unit.wait); /* activate unit */
tto1_unit.buf = AC & 0377; } /* load buffer */
return AC;
}
/* Unit service */
t_stat tto1_svc (UNIT *uptr)
{
int32 out, temp;
int_req = int_req | INT_TTO1; /* set flag */
out = tto1_unit.buf & 0177;
if (!(tto1_unit.flags & UNIT_UC) ||
((out >= 007) && (out <= 0137))) {
temp = sim_putcons (out, uptr);
if (temp != SCPE_OK) return temp;
tto1_unit.pos = tto1_unit.pos + 1; }
return SCPE_OK;
}
/* Reset routine */
t_stat tto1_reset (DEVICE *dptr)
{
tto1_unit.buf = 0; /* clear buffer */
int_req = int_req & ~INT_TTO1; /* clear flag */
sim_cancel (&tto1_unit); /* deactivate unit */
tto1_unit.filebuf = tto1_consout; /* set buf pointer */
return SCPE_OK;
}

View file

@ -28,6 +28,7 @@
tti keyboard
tto teleprinter
10-Jun-01 RMS Fixed comment
30-Oct-00 RMS Standardized device naming
*/
@ -260,7 +261,7 @@ static const int32 boot_rom[] = {
0327776, /* dio x */
0107776, /* xct x */
0730002, /* rpb + wait */
0760400, /* x, halt /
0760400, /* x, halt */
0607772 /* jmp r */
};

View file

@ -23,6 +23,7 @@
be used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from Robert M Supnik.
27-May-01 RMS Added multiconsole support
14-Mar-01 RMS Revised load/dump interface (again)
30-Oct-00 RMS Added support for examine to file
27-Oct-98 RMS V2.4 load interface
@ -50,6 +51,7 @@ extern int32 sc_map[];
sim_PC pointer to saved PC register descriptor
sim_emax number of words for examine
sim_devices array of pointers to simulated devices
sim_consoles array of pointers to consoles (if more than one)
sim_stop_messages array of pointers to stop messages
sim_load binary loader
*/
@ -64,6 +66,8 @@ DEVICE *sim_devices[] = { &cpu_dev,
&ptr_dev, &ptp_dev, &tti_dev, &tto_dev,
&lpt_dev, NULL };
UNIT *sim_consoles = NULL;
const char *sim_stop_messages[] = {
"Unknown error",
"Undefined instruction",
@ -98,11 +102,11 @@ int32 origin, val;
if ((*cptr != 0) || (flag != 0)) return SCPE_ARG;
for (;;) {
if ((val = getword (fileref)) < 0) return SCPE_FMT;
if ((val & 0770000) == 0240000) { /* DAC? */
if ((val & 0770000) == 0240000) { /* DAC? */
origin = val & 07777;
if ((val = getword (fileref)) < 0) return SCPE_FMT;
if (MEM_ADDR_OK (origin)) M[origin++] = val; }
else if ((val & 0770000) == 0600000) {
else if ((val & 0770000) == 0600000) { /* JMP? */
PC = val & 007777;
return SCPE_OK; } }
return SCPE_FMT; /* error */

View file

@ -25,6 +25,7 @@
cpu central processor
07-Jun-01 RMS Fixed bug in JMS to non-existent memory
25-Apr-01 RMS Added device enable/disable support
18-Mar-01 RMS Added DF32 support
05-Mar-01 RMS Added clock calibration support
@ -345,6 +346,10 @@ sim_interval = sim_interval - 1;
jump calculations. Data calculations return a full 15b extended
address, jump calculations a 12b field-relative address.
Autoindex calculations always occur within the same field as the
instruction fetch. The field must exist; otherwise, the instruction
fetched would be 0000, and indirect addressing could not occur.
Note that MA contains IF'PC.
*/
@ -408,12 +413,12 @@ case 007: /* TAD, indir, curr */
case 010: /* ISZ, dir, zero */
ZERO_PAGE;
M[MA] = MB = (M[MA] + 1) & 07777;
M[MA] = MB = (M[MA] + 1) & 07777; /* field must exist */
if (MB == 0) PC = (PC + 1) & 07777;
break;
case 011: /* ISZ, dir, curr */
CURR_PAGE;
M[MA] = MB = (M[MA] + 1) & 07777;
M[MA] = MB = (M[MA] + 1) & 07777; /* field must exist */
if (MB == 0) PC = (PC + 1) & 07777;
break;
case 012: /* ISZ, indir, zero */
@ -461,13 +466,17 @@ case 017: /* DCA, indir, curr */
case 020: /* JMS, dir, zero */
ZERO_PAGE_J;
CHANGE_FIELD;
M[IF | MA] = old_PC = PC;
MA = IF | MA;
old_PC = PC;
if (MEM_ADDR_OK (MA)) M[MA] = PC;
PC = (MA + 1) & 07777;
break;
case 021: /* JMS, dir, curr */
CURR_PAGE_J;
CHANGE_FIELD;
M[IF | MA] = old_PC = PC;
MA = IF | MA;
old_PC = PC;
if (MEM_ADDR_OK (MA)) M[MA] = PC;
PC = (MA + 1) & 07777;
break;
case 022: /* JMS, indir, zero */

View file

@ -29,7 +29,7 @@
19-Mar-01 RMS Added disk monitor bootstrap, fixed IOT decoding
15-Feb-01 RMS Fixed 3 cycle data break sequence
14-Apr-99 RMS Changed t_addr to unsigned
30-Mar-98 RMS Fixed bug in RF bootstrap.
30-Mar-98 RMS Fixed bug in RF bootstrap
The RF08 is a head-per-track disk. It uses the three cycle data break
facility. To minimize overhead, the entire RF08 is buffered in memory.

View file

@ -23,6 +23,7 @@
be used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from Robert M Supnik.
27-May-01 RMS Added multiconsole support
18-Mar-01 RMS Added DF32 support
14-Mar-01 RMS Added extension detection of RIM binary tapes
15-Feb-01 RMS Added DECtape support
@ -53,6 +54,7 @@ extern int32 sim_switches;
sim_PC pointer to saved PC register descriptor
sim_emax maximum number of words for examine/deposit
sim_devices array of pointers to simulated devices
sim_consoles array of pointers to consoles (if more than one)
sim_stop_messages array of pointers to stop messages
sim_load binary loader
*/
@ -73,6 +75,8 @@ DEVICE *sim_devices[] = {
&dt_dev, &mt_dev,
NULL };
UNIT *sim_consoles = NULL;
const char *sim_stop_messages[] = {
"Unknown error",
"Unimplemented instruction",

380
scp.c
View file

@ -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 Robert M Supnik.
12-Jun-01 RMS Fixed bug in big-endian I/O (found by Dave Conroy)
27-May-01 RMS Added multiple console support
16-May-01 RMS Added logging
15-May-01 RMS Added features from Tim Litt
12-May-01 RMS Fixed missing return in disable_cmd
25-Mar-01 RMS Added ENABLE/DISABLE
14-Mar-01 RMS Revised LOAD/DUMP interface (again)
@ -53,7 +57,6 @@
#define SCP 1 /* defining module */
#include "sim_defs.h"
#include <limits.h>
#include <signal.h>
#include <ctype.h>
#define EX_D 0 /* deposit */
@ -83,6 +86,7 @@
extern char sim_name[];
extern DEVICE *sim_devices[];
extern UNIT *sim_consoles[];
extern REG *sim_PC;
extern char *sim_stop_messages[];
extern t_stat sim_instr (void);
@ -96,6 +100,7 @@ extern t_stat ttinit (void);
extern t_stat ttrunstate (void);
extern t_stat ttcmdstate (void);
extern t_stat ttclose (void);
extern t_stat sim_putchar (int32 out);
extern uint32 sim_os_msec (void);
UNIT *sim_clock_queue = NULL;
int32 sim_interval = 0;
@ -106,7 +111,8 @@ static uint32 sim_rtime;
static int32 noqueue_time;
volatile int32 stop_cpu = 0;
t_value *sim_eval = NULL;
int32 sim_end = 1; /* 1 = little, 0 = big */
int32 sim_end = 1; /* 1 = little */
FILE *sim_log = NULL; /* log file */
unsigned char sim_flip[FLIP_SIZE];
#define print_val(a,b,c,d) fprint_val (stdout, (a), (b), (c), (d))
@ -153,6 +159,8 @@ void put_rval (REG *rptr, int idx, t_value val);
t_stat get_aval (t_addr addr, DEVICE *dptr, UNIT *uptr);
t_value strtotv (char *inptr, char **endptr, int radix);
t_stat fprint_val (FILE *stream, t_value val, int rdx, int wid, int fmt);
void fprint_stopped (FILE *stream, t_stat r);
void sim_chkcons (void);
char *read_line (char *ptr, int size, FILE *stream);
DEVICE *find_dev (char *ptr);
DEVICE *find_unit (char *ptr, int32 *iptr);
@ -201,7 +209,9 @@ const char *scp_error_messages[] = {
"Console terminal setup error",
"Subscript out of range",
"Command not allowed",
"Unit disabled"
"Unit disabled",
"Logging enabled",
"Logging disabled"
};
const size_t size_map[] = { sizeof (int8),
@ -255,6 +265,8 @@ t_stat add_cmd (int flag, char *ptr);
t_stat remove_cmd (int flag, char *ptr);
t_stat enable_cmd (int flag, char *ptr);
t_stat disable_cmd (int flag, char *ptr);
t_stat log_cmd (int flag, char *ptr);
t_stat nolog_cmd (int flag, char *ptr);
t_stat help_cmd (int flag, char *ptr);
static CTAB cmd_table[] = {
@ -284,12 +296,14 @@ static CTAB cmd_table[] = {
{ "DISABLE", &disable_cmd, 0 },
{ "ADD", &add_cmd, 0 },
{ "REMOVE", &remove_cmd, 0 },
{ "LOG", &log_cmd, 0 },
{ "NOLOG", &nolog_cmd, 0 },
{ "HELP", &help_cmd, 0 },
{ NULL, NULL, 0 } };
/* Main command loop */
printf ("\n%s simulator V2.6\n", sim_name);
printf ("\n%s simulator V2.6a\n", sim_name);
end_test.i = 1; /* test endian-ness */
sim_end = end_test.c[0];
if (sim_emax <= 0) sim_emax = 1;
@ -306,13 +320,14 @@ sim_time = sim_rtime = 0;
noqueue_time = 0;
sim_clock_queue = NULL;
sim_is_running = 0;
sim_log = NULL;
if ((stat = reset_all (0)) != SCPE_OK) {
printf ("Fatal simulator initialization error\n%s\n",
scp_error_messages[stat - SCPE_BASE]);
return 0; }
if ((argc > 1) && (argv[1] != NULL) &&
((fpin = fopen (argv[1], "r")) != NULL)) { /* command file? */
if ((argc > 1) && (argv[1] != NULL)) { /* cmd line arg? */
if ((fpin = fopen (argv[1], "r")) != NULL) { /* cmd file open? */
do { cptr = read_line (cbuf, CBUFSIZE, fpin);
if (cptr == NULL) break; /* exit on eof */
if (*cptr == 0) continue; /* ignore blank */
@ -324,23 +339,28 @@ if ((argc > 1) && (argv[1] != NULL) &&
if (stat >= SCPE_BASE)
printf ("%s\n", scp_error_messages[stat - SCPE_BASE]);
} while (stat != SCPE_EXIT); } /* end if cmd file */
else printf ("Can't open file \"%s\"\n", argv[1]); } /* end if cmd arg */
do { printf ("sim> "); /* prompt */
cptr = read_line (cbuf, CBUFSIZE, stdin); /* read command line */
stat = SCPE_UNK;
if (cptr == NULL) continue; /* ignore EOF */
if (*cptr == 0) continue; /* ignore blank */
if (sim_log) fprintf (sim_log, "sim> %s\n", cbuf); /* log cmd */
cptr = get_glyph (cptr, gbuf, 0); /* get command glyph */
for (i = 0; cmd_table[i].name != NULL; i++) {
if (MATCH_CMD (gbuf, cmd_table[i].name) == 0) {
stat = cmd_table[i].action (cmd_table[i].arg, cptr);
break; } }
if (stat >= SCPE_BASE)
if (stat >= SCPE_BASE) { /* error? */
printf ("%s\n", scp_error_messages[stat - SCPE_BASE]);
if (sim_log) fprintf (sim_log, "%s\n",
scp_error_messages[stat - SCPE_BASE]); }
} while (stat != SCPE_EXIT);
detach_all (0);
ttclose ();
detach_all (0); /* close files */
nolog_cmd (0, NULL); /* close log */
ttclose (); /* close console */
return 0;
}
@ -353,36 +373,45 @@ return SCPE_EXIT;
/* Help command */
void fprint_help (FILE *st)
{
fprintf (st, "r{eset} {ALL|<device>} reset simulator\n");
fprintf (st, "e{xamine} <list> examine memory or registers\n");
fprintf (st, "ie{xamine} <list> interactive examine memory or registers\n");
fprintf (st, "d{eposit} <list> <val> deposit in memory or registers\n");
fprintf (st, "id{eposit} <list> interactive deposit in memory or registers\n");
fprintf (st, "l{oad} <file> {<args>} load binary file\n");
fprintf (st, "du(mp) <file> {<args>} dump binary file\n");
fprintf (st, "ru{n} {new PC} reset and start simulation\n");
fprintf (st, "go {new PC} start simulation\n");
fprintf (st, "c{ont} continue simulation\n");
fprintf (st, "s{tep} {n} simulate n instructions\n");
fprintf (st, "b{oot} <device>|<unit> bootstrap device\n");
fprintf (st, "at{tach} <unit> <file> attach file to simulated unit\n");
fprintf (st, "det{ach} <unit> detach file from simulated unit\n");
fprintf (st, "sa{ve} <file> save simulator to file\n");
fprintf (st, "rest{ore}|ge{t} <file> restore simulator from file\n");
fprintf (st, "exi{t}|q{uit}|by{e} exit from simulation\n");
fprintf (st, "set <unit> <val> set unit parameter\n");
fprintf (st, "show <device> show device parameters\n");
fprintf (st, "sh{ow} c{onfiguration} show configuration\n");
fprintf (st, "sh{ow} m{odifiers} show modifiers\n");
fprintf (st, "sh{ow} q{ueue} show event queue\n");
fprintf (st, "sh{ow} t{ime} show simulated time\n");
fprintf (st, "en{able} <device> enable device\n");
fprintf (st, "di{sable} <device> disable device\n");
fprintf (st, "ad{d} <unit> add unit to configuration\n");
fprintf (st, "rem{ove} <unit> remove unit from configuration\n");
fprintf (st, "log <file> enable logging to file\n");
fprintf (st, "nolog disable logging\n");
fprintf (st, "h{elp} type this message\n");
return;
}
t_stat help_cmd (int flag, char *cptr)
{
printf ("r{eset} {ALL|<device>} reset simulator\n");
printf ("e{xamine} <list> examine memory or registers\n");
printf ("ie{xamine} <list> interactive examine memory or registers\n");
printf ("d{eposit} <list> <val> deposit in memory or registers\n");
printf ("id{eposit} <list> interactive deposit in memory or registers\n");
printf ("l{oad} <file> {<args>} load binary file\n");
printf ("du(mp) <file> {<args>} dump binary file\n");
printf ("ru{n} {new PC} reset and start simulation\n");
printf ("go {new PC} start simulation\n");
printf ("c{ont} continue simulation\n");
printf ("s{tep} {n} simulate n instructions\n");
printf ("b{oot} <device>|<unit> bootstrap device\n");
printf ("at{tach} <unit> <file> attach file to simulated unit\n");
printf ("det{ach} <unit> detach file from simulated unit\n");
printf ("sa{ve} <file> save simulator to file\n");
printf ("rest{ore}|ge{t} <file> restore simulator from file\n");
printf ("exi{t}|q{uit}|by{e} exit from simulation\n");
printf ("set <unit> <val> set unit parameter\n");
printf ("show <device> show device parameters\n");
printf ("sh{ow} c{onfiguration} show configuration\n");
printf ("sh{ow} m{odifiers} show modifiers\n");
printf ("sh{ow} q{ueue} show event queue\n");
printf ("sh{ow} t{ime} show simulated time\n");
printf ("en{able} <device> enable device\n");
printf ("di{sable} <device> disable device\n");
printf ("ad{d} <unit> add unit to configuration\n");
printf ("rem{ove} <unit> remove unit from configuration\n");
printf ("h{elp} type this message\n");
fprint_help (stdout);
if (sim_log) fprint_help (sim_log);
return SCPE_OK;
}
@ -441,13 +470,16 @@ return SCPE_OK;
t_stat show_cmd (int flag, char *cptr)
{
int32 i;
t_stat r;
char gbuf[CBUFSIZE];
DEVICE *dptr;
t_stat show_config (int flag);
t_stat show_queue (int flag);
t_stat show_time (int flag);
t_stat show_modifiers (int flag);
t_stat show_device (DEVICE *dptr, int flag);
t_stat show_config (FILE *st, int flag);
t_stat show_queue (FILE *st, int flag);
t_stat show_time (FILE *st, int flag);
t_stat show_modifiers (FILE *st, int flag);
t_stat show_device (FILE *st, DEVICE *dptr, int flag);
static CTAB show_table[] = {
{ "CONFIGURATION", &show_config, 0 },
{ "DEVICES", &show_config, 1 },
@ -460,110 +492,118 @@ GET_SWITCHES (cptr, gbuf); /* test for switches */
cptr = get_glyph (cptr, gbuf, 0); /* get next glyph */
if (*cptr != 0) return SCPE_ARG; /* now eol? */
for (i = 0; show_table[i].name != NULL; i++) { /* find command */
if (MATCH_CMD (gbuf, show_table[i].name) == 0)
return show_table[i].action (show_table[i].arg); }
if (MATCH_CMD (gbuf, show_table[i].name) == 0) {
r = show_table[i].action (stdout, show_table[i].arg);
if (sim_log)
show_table[i].action (sim_log, show_table[i].arg);
return r; } }
dptr = find_dev (gbuf); /* locate device */
if (dptr == NULL) return SCPE_ARG; /* not found? */
return show_device (dptr, 0);
r = show_device (stdout, dptr, 0);
if (sim_log) show_device (sim_log, dptr, 0);
return r;
}
/* Show processors */
t_stat show_device (DEVICE *dptr, int flag)
t_stat show_device (FILE *st, DEVICE *dptr, int flag)
{
int32 j, ucnt;
t_addr kval;
UNIT *uptr;
MTAB *mptr;
printf ("%s", dptr -> name); /* print dev name */
fprintf (st, "%s", dptr -> name); /* print dev name */
if (qdisable (dptr)) { /* disabled? */
printf (", disabled\n");
fprintf (st, ", disabled\n");
return SCPE_OK; }
for (j = ucnt = 0; j < dptr -> numunits; j++) { /* count units */
uptr = (dptr -> units) + j;
if (!(uptr -> flags & UNIT_DIS)) ucnt++; }
if (dptr -> numunits == 0) printf ("\n");
else { if (ucnt == 0) printf (", all units disabled\n");
else if (ucnt > 1) printf (", %d units\n", ucnt);
else if (flag) printf ("\n"); }
if (dptr -> numunits == 0) fprintf (st, "\n");
else { if (ucnt == 0) fprintf (st, ", all units disabled\n");
else if (ucnt > 1) fprintf (st, ", %d units\n", ucnt);
else if (flag) fprintf (st, "\n"); }
if (flag) return SCPE_OK; /* dev only? */
for (j = 0; j < dptr -> numunits; j++) {
uptr = (dptr -> units) + j;
kval = (uptr -> flags & UNIT_BINK)? 1024: 1000;
if (uptr -> flags & UNIT_DIS) continue;
if (ucnt > 1) printf (" unit %d", j);
if (ucnt > 1) fprintf (st, " unit %d", j);
if (uptr -> flags & UNIT_FIX) {
if (uptr -> capac < kval)
printf (", %d%s", uptr -> capac,
fprintf (st, ", %d%s", uptr -> capac,
((dptr -> dwidth / dptr -> aincr) > 8)? "W": "B");
else printf (", %dK%s", uptr -> capac / kval,
else fprintf (st, ", %dK%s", uptr -> capac / kval,
((dptr -> dwidth / dptr -> aincr) > 8)? "W": "B"); }
if (uptr -> flags & UNIT_ATT)
printf (", attached to %s", uptr -> filename);
else if (uptr -> flags & UNIT_ATTABLE) printf (", not attached");
fprintf (st, ", attached to %s", uptr -> filename);
else if (uptr -> flags & UNIT_ATTABLE)
fprintf (st, ", not attached");
if (dptr -> modifiers != NULL) {
for (mptr = dptr -> modifiers; mptr -> mask != 0; mptr++) {
if ((mptr -> pstring != NULL) &&
((uptr -> flags & mptr -> mask) == mptr -> match))
printf (", %s", mptr -> pstring); } }
printf ("\n"); }
fprintf (st, ", %s", mptr -> pstring); } }
fprintf (st, "\n"); }
return SCPE_OK;
}
t_stat show_config (int flag)
t_stat show_config (FILE *st, int flag)
{
int32 i;
DEVICE *dptr;
printf ("%s simulator configuration\n\n", sim_name);
fprintf (st, "%s simulator configuration\n\n", sim_name);
for (i = 0; (dptr = sim_devices[i]) != NULL; i++)
show_device (dptr, flag);
show_device (st, dptr, flag);
return SCPE_OK;
}
t_stat show_queue (int flag)
t_stat show_queue (FILE *st, int flag)
{
DEVICE *dptr;
UNIT *uptr;
int32 accum;
if (sim_clock_queue == NULL) {
printf ("%s event queue empty, time = %-16.0f\n", sim_name, sim_time);
fprintf (st, "%s event queue empty, time = %-16.0f\n",
sim_name, sim_time);
return SCPE_OK; }
printf ("%s event queue status, time = %-16.0f\n", sim_name, sim_time);
fprintf (st, "%s event queue status, time = %-16.0f\n",
sim_name, sim_time);
accum = 0;
for (uptr = sim_clock_queue; uptr != NULL; uptr = uptr -> next) {
if (uptr == &step_unit) printf (" Step timer");
if (uptr == &step_unit) fprintf (st, " Step timer");
else if ((dptr = find_dev_from_unit (uptr)) != NULL) {
printf (" %s", dptr -> name);
if (dptr -> numunits > 1) printf (" unit %d",
fprintf (st, " %s", dptr -> name);
if (dptr -> numunits > 1) fprintf (st, " unit %d",
uptr - dptr -> units); }
else printf (" Unknown");
printf (" at %d\n", accum + uptr -> time);
else fprintf (st, " Unknown");
fprintf (st, " at %d\n", accum + uptr -> time);
accum = accum + uptr -> time; }
return SCPE_OK;
}
t_stat show_time (int flag)
t_stat show_time (FILE *st, int flag)
{
printf ("Time: %-16.0f\n", sim_time);
fprintf (st, "Time: %-16.0f\n", sim_time);
return SCPE_OK;
}
t_stat show_modifiers (int flag)
t_stat show_modifiers (FILE *st, int flag)
{
int i, any;
DEVICE *dptr;
MTAB *mptr;
for (i = 0; (dptr = sim_devices[i]) != NULL; i++) {
any = 0;
for (mptr = dptr -> modifiers; mptr && (mptr -> mask != 0); mptr++) {
if (mptr -> mstring) {
if (any++) printf (", %s", mptr -> mstring);
else printf ("%s %s", dptr -> name, mptr -> mstring); } }
if (any) printf ("\n"); }
any = 0;
for (mptr = dptr -> modifiers; mptr && (mptr -> mask != 0); mptr++) {
if (mptr -> mstring) {
if (any++) fprintf (st, ", %s", mptr -> mstring);
else fprintf (st, "%s %s", dptr -> name, mptr -> mstring); } }
if (any) fprintf (st, "\n"); }
return SCPE_OK;
}
@ -668,6 +708,43 @@ uptr -> flags = uptr -> flags | UNIT_DIS; /* disable it */
return SCPE_OK;
}
/* Logging commands
log filename open log file
nolog close log file
*/
t_stat log_cmd (int flag, char *cptr)
{
char gbuf[CBUFSIZE];
GET_SWITCHES (cptr, gbuf); /* test for switches */
if (*cptr == 0) return (sim_log? SCPE_LOGON: SCPE_LOGOFF);
cptr = get_glyph_nc (cptr, gbuf, 0); /* get file name */
if (*cptr != 0) return SCPE_ARG; /* end of line? */
nolog_cmd (0, NULL); /* close cur log */
sim_log = fopen (gbuf, "a"); /* open log */
if (sim_log == NULL) return SCPE_OPENERR; /* error? */
printf ("Logging to file \"%s\"\n", gbuf); /* start of log */
fprintf (sim_log, "Logging to file \"%s\"\n", gbuf);
return SCPE_OK;
}
t_stat nolog_cmd (int flag, char *cptr)
{
char gbuf[CBUFSIZE];
if (cptr) {
GET_SWITCHES (cptr, gbuf); /* test for switches */
if (*cptr != 0) return SCPE_ARG; } /* end of line? */
if (sim_log == NULL) return SCPE_OK; /* no log? */
printf ("Log file closed\n");
fprintf (sim_log, "Log file closed\n"); /* close log */
fclose (sim_log);
sim_log = NULL;
return SCPE_OK;
}
/* Reset command and routines
re[set] reset all devices
@ -991,7 +1068,7 @@ else if (strcmp (buf, save_ver25) == 0) { /* version 2.5? */
if (strcmp (buf, sim_name)) { /* name match? */
printf ("Wrong system type: %s\n", buf);
fclose (rfile);
return SCPE_OK; }
return SCPE_INCOMP; }
READ_I (sim_time); /* sim time */
if (v26) { READ_I (sim_rtime); } /* sim relative time */
@ -1095,8 +1172,6 @@ t_stat run_cmd (int flag, char *cptr)
char gbuf[CBUFSIZE];
int32 i, j, step, unitno;
t_stat r;
t_addr k;
t_value pcval;
DEVICE *dptr;
UNIT *uptr;
void int_handler (int signal);
@ -1147,6 +1222,7 @@ if (ttrunstate () != SCPE_OK) { /* set console */
return SCPE_TTYERR; }
if (step) sim_activate (&step_unit, step); /* set step timer */
sim_is_running = 1; /* flag running */
sim_chkcons (); /* check console buffer */
r = sim_instr();
sim_is_running = 0; /* flag idle */
@ -1159,11 +1235,26 @@ else { UPDATE_SIM_TIME (noqueue_time); }
#if defined (VMS)
printf ("\n");
#endif
if (r >= SCPE_BASE) printf ("\n%s, %s: ", scp_error_messages[r - SCPE_BASE],
sim_PC -> name);
else printf ("\n%s, %s: ", sim_stop_messages[r], sim_PC -> name);
fprint_stopped (stdout, r); /* print msg */
if (sim_log) fprint_stopped (sim_log, r); /* log if enabled */
return SCPE_OK;
}
/* Print stopped message */
void fprint_stopped (FILE *stream, t_stat v)
{
int32 i;
t_stat r;
t_addr k;
t_value pcval;
DEVICE *dptr;
if (v >= SCPE_BASE) fprintf (stream, "\n%s, %s: ",
scp_error_messages[v - SCPE_BASE], sim_PC -> name);
else fprintf (stream, "\n%s, %s: ", sim_stop_messages[v], sim_PC -> name);
pcval = get_rval (sim_PC, 0);
print_val (pcval, sim_PC -> radix, sim_PC -> width,
fprint_val (stream, pcval, sim_PC -> radix, sim_PC -> width,
sim_PC -> flags & REG_FMT);
if (((dptr = sim_devices[0]) != NULL) && (dptr -> examine != NULL)) {
for (i = 0; i < sim_emax; i++) sim_eval[i] = 0;
@ -1171,16 +1262,14 @@ if (((dptr = sim_devices[0]) != NULL) && (dptr -> examine != NULL)) {
if (r = dptr -> examine (&sim_eval[i], k, dptr -> units,
SWMASK ('V')) != SCPE_OK) break; }
if ((r == SCPE_OK) || (i > 0)) {
printf (" (");
if (fprint_sym (stdout, (t_addr) pcval, sim_eval, NULL, SWMASK('M')) > 0)
fprint_val (stdout, sim_eval[0], dptr -> dradix,
fprintf (stream, " (");
if (fprint_sym (stream, (t_addr) pcval, sim_eval, NULL, SWMASK('M')) > 0)
fprint_val (stream, sim_eval[0], dptr -> dradix,
dptr -> dwidth, PV_RZRO);
printf (")"); } }
printf ("\n");
return SCPE_OK;
fprintf (stream, ")"); } }
fprintf (stream, "\n");
return;
}
/* Run time routines */
/* Unit service for step timeout, originally scheduled by STEP n command
@ -1227,7 +1316,7 @@ t_stat exdep_cmd (int flag, char *cptr)
{
char gbuf[CBUFSIZE], *gptr, *tptr;
int32 unitno, t;
t_bool log;
t_bool exd2f;
t_addr low, high;
t_stat reason;
DEVICE *dptr, *tdptr;
@ -1242,7 +1331,7 @@ t_stat exdep_reg_loop (FILE *ofile, SCHTAB *schptr, int flag, char *ptr,
if (*cptr == 0) return SCPE_ARG; /* err if no args */
ofile = NULL; /* no output file */
log = FALSE;
exd2f = FALSE;
sim_switches = 0; /* no switches */
schptr = NULL; /* no search */
stab.logic = SCH_OR; /* default search params */
@ -1254,13 +1343,13 @@ for (;;) { /* loop through modifiers */
if (*cptr == 0) return SCPE_ARG; /* error if no arguments */
if (*cptr == '@') { /* output file spec? */
if (flag != EX_E) return SCPE_ARG; /* examine only */
if (log) { /* already got one? */
if (exd2f) { /* already got one? */
fclose (ofile); /* one per customer */
return SCPE_ARG; }
cptr = get_glyph_nc (cptr + 1, gbuf, 0);
ofile = fopen (gbuf, "a"); /* open for append */
if (ofile == NULL) return SCPE_OPENERR;
log = TRUE;
exd2f = TRUE;
continue; } /* look for more */
cptr = get_glyph (cptr, gbuf, 0);
if ((t = get_switches (gbuf)) != 0) { /* try for switches */
@ -1313,7 +1402,7 @@ for (gptr = gbuf, reason = SCPE_OK;
reason = exdep_addr_loop (ofile, schptr, flag, cptr, low, high,
dptr, uptr);
} /* end for */
if (log) fclose (ofile); /* close output file */
if (exd2f) fclose (ofile); /* close output file */
return reason;
}
@ -1342,7 +1431,9 @@ for (rptr = lowr; rptr <= highr; rptr++) {
if (schptr && !test_search (val, schptr)) continue;
if (flag != EX_D) {
reason = ex_reg (ofile, val, flag, rptr, idx);
if (reason != SCPE_OK) return reason; }
if (reason != SCPE_OK) return reason;
if (sim_log && (ofile == stdout))
ex_reg (sim_log, val, flag, rptr, idx); }
if (flag != EX_E) {
reason = dep_reg (flag, cptr, rptr, idx);
if (reason != SCPE_OK) return reason; } } }
@ -1365,7 +1456,9 @@ for (i = low; i <= high; i = i + (dptr -> aincr)) {
if (schptr && !test_search (sim_eval[0], schptr)) continue;
if (flag != EX_D) {
reason = ex_addr (ofile, flag, i, dptr, uptr);
if (reason > SCPE_OK) return reason; }
if (reason > SCPE_OK) return reason;
if (sim_log && (ofile == stdout))
ex_addr (sim_log, flag, i, dptr, uptr); }
if (flag != EX_E) {
reason = dep_addr (flag, cptr, i, dptr, uptr, reason);
if (reason > SCPE_OK) return reason; }
@ -1452,6 +1545,7 @@ if ((cptr == NULL) || (rptr == NULL)) return SCPE_ARG;
if (rptr -> flags & REG_RO) return SCPE_RO;
if (flag & EX_I) {
cptr = read_line (gbuf, CBUFSIZE, stdin);
if (sim_log) fprintf (sim_log, (cptr? "%s\n": "\n"), cptr);
if (cptr == NULL) return 1; /* force exit */
if (*cptr == 0) return SCPE_OK; } /* success */
mask = width_mask[rptr -> width];
@ -1606,6 +1700,7 @@ char gbuf[CBUFSIZE];
if (dptr == NULL) return SCPE_ARG;
if (flag & EX_I) {
cptr = read_line (gbuf, CBUFSIZE, stdin);
if (sim_log) fprintf (sim_log, (cptr? "%s\n": "\n"), cptr);
if (cptr == NULL) return 1; /* force exit */
if (*cptr == 0) return dfltinc; } /* success */
mask = width_mask[dptr -> dwidth];
@ -1661,6 +1756,7 @@ if (cptr == NULL) {
for (tptr = cptr; tptr < (cptr + size); tptr++) /* remove cr */
if (*tptr == '\n') *tptr = 0;
while (isspace (*cptr)) cptr++; /* absorb spaces */
if (*cptr == ';') *cptr = 0; /* ignore comment */
return cptr;
}
@ -2267,11 +2363,12 @@ lcnt = count % nelem; /* count in last buf */
if (lcnt) nbuf = nbuf + 1;
else lcnt = nelem;
total = 0;
dptr = bptr; /* init output ptr */
for (i = nbuf; i > 0; i--) {
c = fread (sim_flip, size, (i == 1? lcnt: nelem), fptr);
if (c == 0) return total;
total = total + c;
for (j = 0, sptr = sim_flip, dptr = bptr; j < c; j++) {
for (j = 0, sptr = sim_flip; j < c; j++) {
for (k = size - 1; k >= 0; k--) *(dptr + k) = *sptr++;
dptr = dptr + size; } }
return total;
@ -2292,11 +2389,11 @@ lcnt = count % nelem; /* count in last buf */
if (lcnt) nbuf = nbuf + 1;
else lcnt = nelem;
total = 0;
sptr = bptr; /* init input ptr */
for (i = nbuf; i > 0; i--) {
c = (i == 1)? lcnt: nelem;
for (j = 0, sptr = bptr, dptr = sim_flip; j < c; j++) {
for (k = size - 1; k >= 0; k--)
*(dptr + k) = *sptr++;
for (j = 0, dptr = sim_flip; j < c; j++) {
for (k = size - 1; k >= 0; k--) *(dptr + k) = *sptr++;
dptr = dptr + size; }
c = fwrite (sim_flip, size, c, fptr);
if (c == 0) return total;
@ -2354,4 +2451,77 @@ rtc_currdelay = (int32) (((double) rtc_basedelay * (double) rtc_nextintv) /
1000.0); /* next delay */
return rtc_currdelay;
}
/* OS independent multiconsole package
set_console make unit the active console
sim_putcons output character in a multiconsole simulator
sim_chkcons check for buffered output in a multiconsole simulator
*/
t_stat set_console (UNIT *uptr, int32 flag)
{
int32 i;
DEVICE *idptr, *odptr;
UNIT *wuptr, *iuptr = NULL, *ouptr = NULL;
if (sim_consoles == NULL) return SCPE_NOFNC;
for (i = 0; sim_consoles[i] != NULL; i++) {
if (uptr == sim_consoles[i]) {
iuptr = sim_consoles[i & ~1];
ouptr = sim_consoles[i | 1]; } }
if ((iuptr == NULL) || (ouptr == NULL)) return SCPE_ARG;
idptr = find_dev_from_unit (iuptr);
odptr = find_dev_from_unit (ouptr);
if ((idptr == NULL) || (odptr == NULL)) return SCPE_ARG;
for (i = 0; sim_consoles[i] != NULL; i++) {
wuptr = sim_consoles[i];
wuptr -> flags = wuptr -> flags & ~UNIT_CONS;
if (!(i & 1)) sim_cancel (wuptr); }
iuptr -> flags = iuptr -> flags | UNIT_CONS;
ouptr -> flags = ouptr -> flags | UNIT_CONS;
sim_activate (iuptr, iuptr -> wait);
if (idptr == odptr) {
printf ("Active console is %s\n", idptr -> name);
if (sim_log) fprintf (sim_log, "Active console is %s\n", idptr -> name); }
else { printf ("Active console is %s/%s\n", idptr -> name, odptr -> name);
if (sim_log) fprintf (sim_log,
"Active console is %s/%s\n", idptr -> name, odptr -> name); }
return SCPE_OK;
}
t_stat sim_putcons (int32 out, UNIT *uptr)
{
uint8 *consbuf;
if ((uptr -> flags & UNIT_CONS) || (uptr -> filebuf == NULL))
return sim_putchar (out);
if (uptr -> u4 < CONS_SIZE) {
consbuf = (uint8 *) uptr -> filebuf;
consbuf[uptr -> u4] = out; }
uptr -> u4 = uptr -> u4 + 1;
return SCPE_OK;
}
void sim_chkcons (void)
{
int32 i, j, limit;
uint8 *consbuf;
UNIT *uptr;
if (sim_consoles == NULL) return;
for (i = 0; sim_consoles[i] != NULL; i++) {
uptr = sim_consoles[i];
if ((i & 1) && (uptr -> flags & UNIT_CONS) &&
(uptr -> filebuf) && (uptr -> u4)) {
consbuf = (uint8 *) uptr -> filebuf;
limit = (uptr -> u4 < CONS_SIZE)? uptr -> u4: CONS_SIZE;
for (j = 0; j < limit; j++) sim_putchar (consbuf[j]);
if (uptr -> u4 >= CONS_SIZE) {
printf ("\n[Buffered output lost]\n");
if (sim_log) fprintf (sim_log, "\n[Buffered output lost]\n"); }
uptr -> u4 = 0;
return; } }
return;
}

View file

@ -23,6 +23,7 @@
be used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from Robert M Supnik.
15-May-01 RMS Added logging support
05-Mar-01 RMS Added clock calibration support
08-Dec-00 BKR Added OS/2 support
18-Aug-98 RMS Added BeOS support
@ -50,6 +51,7 @@
#undef USE_INT64 /* hack for Windows */
#include "sim_defs.h"
int32 sim_int_char = 005; /* interrupt character */
extern FILE *sim_log;
/* VMS routines */
@ -151,6 +153,7 @@ IOSB iosb;
c = out;
status = sys$qiow (EFN, tty_chan, IO$_WRITELBLK | IO$M_NOFORMAT,
&iosb, 0, 0, &c, 1, 0, 0, 0, 0);
if (sim_log) fputc (c, sim_log);
if ((status != SS$_NORMAL) || (iosb.status != SS$_NORMAL)) return SCPE_TTOERR;
return SCPE_OK;
}
@ -237,7 +240,9 @@ return c | SCPE_KFLAG;
t_stat sim_putchar (int32 c)
{
if (c != 0177) _putch (c);
if (c != 0177) {
_putch (c);
if (sim_log) fputc (c, sim_log); }
return SCPE_OK;
}
@ -291,7 +296,8 @@ t_stat sim_putchar (int32 c)
{
if (c != 0177) {
putch (c);
fflush (stdout) ; }
fflush (stdout) ;
if (sim_log) fputc (c, sim_log); }
return SCPE_OK;
}
@ -381,6 +387,7 @@ char c;
c = out;
write (1, &c, 1);
if (sim_log) fputc (c, sim_log);
return SCPE_OK;
}
@ -480,6 +487,7 @@ char c;
c = out;
write (1, &c, 1);
if (sim_log) fputc (c, sim_log);
return SCPE_OK;
}

View file

@ -23,6 +23,8 @@
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.
27-May-01 RMS Added multiple console support
15-May-01 RMS Increased string buffer size
25-Feb-01 RMS Revisions for V2.6
15-Oct-00 RMS Editorial revisions for V2.5
11-Jul-99 RMS Added unsigned int data types
@ -53,6 +55,7 @@
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <limits.h>
#ifndef TRUE
#define TRUE 1
@ -90,7 +93,11 @@ typedef int32 t_mtrlnt; /* magtape rec lnt */
#define MTRF(x) ((x) & (1u << 31)) /* record error flg */
#define MTRL(x) ((x) & ((1u << 31) - 1)) /* record length */
#define FLIP_SIZE (1 << 16) /* flip buf size */
#define CBUFSIZE 128 /* string buf size */
#if !defined (PATH_MAX) /* usually in limits */
#define PATH_MAX 512
#endif
#define CBUFSIZE (128 + PATH_MAX) /* string buf size */
#define CONS_SIZE 4096 /* console buffer */
/* Simulator status codes
@ -128,6 +135,8 @@ typedef int32 t_mtrlnt; /* magtape rec lnt */
#define SCPE_SUB (SCPE_BASE + 24) /* subscript err */
#define SCPE_NOFNC (SCPE_BASE + 25) /* func not imp */
#define SCPE_UDIS (SCPE_BASE + 26) /* unit disabled */
#define SCPE_LOGON (SCPE_BASE + 27) /* logging enabled */
#define SCPE_LOGOFF (SCPE_BASE + 28) /* logging disabled */
#define SCPE_KFLAG 01000 /* tti data flag */
/* Print value format codes */
@ -211,7 +220,9 @@ struct unit {
#define UNIT_BUF 000400 /* buffered */
#define UNIT_DISABLE 001000 /* disable-able */
#define UNIT_DIS 002000 /* disabled */
#define UNIT_V_UF 11 /* device specific */
#define UNIT_CONS 004000 /* active console */
#define UNIT_V_CONS 11
#define UNIT_V_UF 12 /* device specific */
/* Register data structure */
@ -310,3 +321,5 @@ EXTERN char *get_glyph (char *iptr, char *optr, char mchar);
EXTERN char *get_glyph_nc (char *iptr, char *optr, char mchar);
EXTERN t_value get_uint (char *cptr, int radix, t_value max, t_stat *status);
EXTERN t_value strtotv (char *cptr, char **endptr, int radix);
EXTERN t_stat set_console (UNIT *uptr, int32 flag);
EXTERN t_stat sim_putcons (int32 out, UNIT *uptr);

806
simh.doc

File diff suppressed because it is too large Load diff

View file

@ -1,7 +1,7 @@
To: Users
From: Bob Supnik
Subj: Simulator Usage, V2.6
Date: 3-May-01
Subj: Simulator Usage, V2.6a
Date: 15-Jun-01
COPYRIGHT NOTICE
@ -161,6 +161,8 @@ Multiple switches may be specified separately or together: -abcd or
-a -b -c -d are treated identically. Verbs, switches, and other
input (except for file names) are case insensitive.
Any command beginning with semicolon (;) is considered a comment and ignored.
3.1 Loading and Saving Programs
The LOAD command (abbreviation LO) loads a file in binary paper-tape
@ -419,7 +421,20 @@ specified unit from the configuration. Once removed, a unit cannot be
manipulated in any way until it is added back to the configuration.
ADD <unit> adds back a unit that had been removed from the configuration.
3.11 Exiting The Simulator
3.11 Logging Console Output
Output to the console can be logged simultaneously to a file. Logging is
enabled by the LOG command:
sim> LOG <filename> -- log console output to file
Logging is disabled by the NOLOG command:
sim> NOLOG -- disable logging
LOG with no argument displays whether logging is enabled or disabled.
3.12 Exiting The Simulator
EXIT (synonyms QUIT and BYE) returns control to the operating system.
@ -1704,6 +1719,22 @@ control registers for the interrupt system.
6.2 Programmed I/O Devices
The Nova can have two terminals (TTI/TTO, TTI1/TTO1). At any moment
only one terminal is active. It can receive input from the keyboard;
it can output to the simulator window. The inactive console cannot
receive input from the keyboard and outputs to an internal buffer
(maximum 4K characters).
Control is switched among terminals with a SET TTI{n} CONSOLE or SET
TTO{n} CONSOLE command:
At startup, active console is TTI/TTO
SET TTI1 CONSOLE Active console is now TTI1/TTO1
SET TTO CONSOLE Active console is now TTI/TTO
When control is switched to an inactive terminal, any buffered output
is printed when simulation resumes.
6.2.1 Paper Tape Reader (PTR)
The paper tape reader (PTR) reads data from a disk file. The POS
@ -1763,21 +1794,23 @@ Error handling is as follows:
OS I/O error x report error and stop
6.2.3 Terminal Input (TTI)
6.2.3 Terminal Input (TTI, TTI1)
The terminal input reads from the controling console port. Terminal
options include the ability to set limited Dasher compatibility mode or
normal mode:
The active terminal input polls the console keyboard for input. The
inactive terminal input cannot receive characters. Terminal input
options include the ability to set limited Dasher compatibility mode
or ANSI standard mode:
SET TTI ANSI normal mode
SET TTI DASHER Dasher mode
SET TTO ANSI normal mode
SET TTO DASHER Dasher mode
Setting either TTI or TTO changes both devices. In Dasher mode, carriage
return is changed to newline on input, and ^X is changed to backspace.
Setting either TTI (TTI1) or TTO (TTO1) changes both devices. In Dasher
mode, carriage return is changed to newline on input, and ^X is changed
to backspace.
The terminal input implements these registers:
The terminal inputs implement these registers:
name size comments
@ -1789,21 +1822,22 @@ The terminal input implements these registers:
POS 31 number of characters input
TIME 24 keyboard polling interval
6.2.4 Terminal Output (TTO)
6.2.4 Terminal Output (TTO, TTO1)
The terminal output writes to the controling console port. Terminal
options include the ability to set limited Dasher compatibility mode or
normal mode:
The active terminal output writes to the simulator window. The inactive
terminal output buffers characters. Terminal output options include the
the ability to set limited Dasher compatibility mode or ANSI mode:
SET TTI ANSI normal mode
SET TTI DASHER Dasher mode
SET TTO ANSI normal mode
SET TTO DASHER Dasher mode
Setting either TTI or TTO changes both devices. In Dasher mode, carriage
return is changed to newline on input, and ^X is changed to backspace.
Setting either TTI (TTI1) or TTO (TTO1) changes both devices. In Dasher
mode, carriage return is changed to newline on input, and ^X is changed
to backspace.
The terminal output implements these registers:
The terminal outputs implement these registers:
name size comments
@ -1890,69 +1924,6 @@ Error handling is as follows:
OS I/O error x report error and stop
6.2.8 Second Terminal Input (TTI1)
The second terminal input (TTI1) reads data from a disk file. When a
file is attached, the second terminal input will read characters at
the interval specified by the TIME register. Detaching the file, or
reaching end of file, stops input. The POS register specifies the
number of the next data item to be read. Thus, by changing POS, the
user can backspace or advance the input stream.
The second terminal input implements these registers:
name size comments
BUF 8 last data item processed
BUSY 1 device busy flag
DONE 1 device done flag
DISABLE 1 interrupt disable flag
INT 1 interrupt pending flag
POS 31 position in the input file
TIME 24 time from I/O initiation to interrupt
STOP_IOE 1 stop on I/O error
Error handling is as follows:
error STOP_IOE processed as
not attached 1 report error and stop
0 out of tape or paper
end of file 1 report error and stop
0 out of tape or paper
OS I/O error x report error and stop
6.2.9 Second Terminal Output (TTO1)
The second terminal output (TTO1) writes data to a disk file. The
POS register specifies the number of the next data item to be written.
Thus, by changing POS, the user can backspace or advance the output
stream.
The second terminal outpout implements these registers:
name size comments
BUF 8 last data item processed
BUSY 1 device busy flag
DONE 1 device done flag
DISABLE 1 interrupt disable flag
INT 1 interrupt pending flag
POS 31 position in the output file
TIME 24 time from I/O initiation to interrupt
STOP_IOE 1 stop on I/O error
Error handling is as follows:
error STOP_IOE processed as
not attached 1 report error and stop
0 out of tape or paper
OS I/O error x report error and stop
6.3 Fixed Head Disk (DK)
The fixed head disk controller implements these registers:
@ -2528,11 +2499,13 @@ PDP-7 CPU PDP-7 CPU with 32KW of memory
PDP-9 CPU PDP-9 CPU with 32KW of memory
- KE09A extended arithmetic element (EAE)
- KF09A automatic priority interrupt (API)
- KG09B memory extension
- KP09A power detection
- KX09A memory protection
PTR,PTP PC09A paper tape reader/punch
TTI,TTO KSR 33 console terminal
TTI1,TTO1 LT09A second console terminal
LPT Type 647E line printer
CLK integral real-time clock
RF RF09/RS09 fixed-head disk
@ -2541,10 +2514,12 @@ PDP-9 CPU PDP-9 CPU with 32KW of memory
PDP-15 CPU PDP-15 CPU with 32KW of memory
- KE15 extended arithmetic element (EAE)
- KA15 automatic priority interrupt (API)
- KF15 power detection
- KM15 memory protection
PTR,PTP PC15 paper tape reader/punch
TTI,TTO KSR 35 console terminal
TTI1,TTO1 LT15 second console terminal
LPT LP15 line printer
CLK integral real-time clock
RP RP15/RP02 disk pack
@ -2569,10 +2544,13 @@ specified, the file is assumed to be BIN format.
8.1 CPU
The only CPU options are the presence of the EAE and the size of main memory.
The CPU options are the presence of the EAE, the presense of the API (for
the PDP-9 and PDP-15), and the size of main memory.
SET CPU EAE enable EAE
SET CPU NOEAE disable EAE
SET CPU API enable API
SET CPU NOAPI disable API
SET CPU 4K set memory size = 4K
SET CPU 8K set memory size = 8K
SET CPU 12K set memory size = 12K
@ -2638,6 +2616,22 @@ the PDP-7 and PDP-9, 17b for the PDP-15).
8.2 Programmed I/O Devices
The PDP-9 and PDP-15 have two terminals (TTI/TTO, TTI1/TTO1). At any
moment, only one terminal is active. It can receive input from the
keyboard; it can output to the simulator window. The inactive console
cannot receive input from the keyboard and outputs to an internal buffer
(maximum 4K characters).
Control is switched among terminals with a SET TTI{n} CONSOLE or SET
TTO{n} CONSOLE command:
At startup, active console is TTI/TTO
SET TTI1 CONSOLE Active console is now TTI1/TTO1
SET TTO CONSOLE Active console is now TTI/TTO
When control is switched to an inactive terminal, any buffered output
is printed when simulation resumes.
8.2.1 Paper Tape Reader (PTR)
The paper tape reader (PTR) reads data from a disk file. The POS
@ -2700,18 +2694,20 @@ Error handling is as follows:
OS I/O error x report error and stop
8.2.3 Terminal Input (TTI)
8.2.3 Terminal Input (TTI, TTI1)
The terminal input (TTI) reads from the controling console port. The
terminal input has one option, UC; when set, it automatically converts
lower case input to upper case.
The active terminal input polls the console keyboard for input. The
inactive terminal input cannot receive characters. The terminal inputs
have one option, UC; when set, it automatically converts lower case input
to upper case.
The PDP-9 and PDP-15 operated the terminal, by default, as half-duplex.
For backward compatibility, on the PDP-9 and PDP-15 the terminal input
has a second option, FDX; when set, it operates the terminal input in
full-duplex mode.
The PDP-9 and PDP-15 operated the primary terminal (TTI/TTO), by default,
as half-duplex. For backward compatibility, on the PDP-9 and PDP-15
the first terminal input has a second option, FDX; when set, it operates
the terminal input in full-duplex mode. The second terminal is always
full duplex.
The terminal input implements these registers:
The terminal inputs implement these registers:
name size comments
@ -2721,10 +2717,14 @@ The terminal input implements these registers:
POS 31 number of characters input
TIME 24 keyboard polling interval
8.2.4 Terminal Output (TTO)n backspace or advance these devices.
8.2.4 Terminal Output (TTO, TTO1)
The terminal output (TTO) writes to the controling console port. It
implements these registers:
The active terminal output writes to the simulator window. The inactive
terminal output buffers characters. The terminal outputs have one option,
UC; when set, it suppresses lower case output (so that ALTMODE is not
echoed as }).
The terminal outputs implement these registers:
name size comments
@ -4172,9 +4172,12 @@ the file format to try to determine the file type.
12.1 CPU
The only CPU option is the choice of standard or ITS compatible microcode.
The CPU options allow the user to specify standard microcode, standard
microcode with a bug fix for a boostrap problem in TOPS-20 V4.1, or ITS
microcode
SET CPU STANDARD Standard microcode
SET CPU TOPS20V41 Standard microcode with TOPS-20 V4.1 bug fix
SET CPU ITS ITS compatible microcode
CPU registers include the visible state of the processor as well as the
@ -4663,12 +4666,22 @@ legend: y = runs operating system or sample program
Revision History (since Rev 1.1)
Rev 2.6a, Jul, 01
Rev 2.6a, Jun, 01
Fixed bug (found by Dave Conroy) in big-endian I/O
Fixed DECtape reset in PDP-8, PDP-11, PDP-9/15
Fixed RIM loader PC handling in PDP-9/15
Fixed indirect pointers in PDP-10 paging
Fixed SSC handling in PDP-10 TM02/TU45
Added FE CTRL-C option for Windoze
Fixed JMS to non-existent memory in PDP-8
Fixed error handling on command file
Increased size of string buffers for long path names
Added PDP-9, PDP-15 API option
Added PDP-9, PDP-15 second terminal
Added PDP-10 option for TOPS-20 V4.1 bug fix
Added PDP-10 FE CTRL-C option for Windoze
Added console logging
Added multiple console support
Added comment recognition
Rev 2.6, May, 01
Added ENABLE/DISABLE devices

View file

@ -457,9 +457,62 @@ To load and run BASIC:
RUN
1.41421
9. PDP-10 TOPS-10 7.03
9. PDP-9/PDP-15 Advanced Software System/Keyboard Monitor
The Advanced Software System was a family of operating systems for the
PDP-9 and PDP-15, ranging from a paper-tape basic system, through the
DECtape or disk based Keyboard Monitor, through the Foreground/Background
Monitor, to DOS-15. To run ADSS/KM from simulated DECtape:
- On the PDP-9 (only), initialize extend mode to on:
sim> d extm_init 1
- Load the paper-tape bootstrap into upper memory:
sim> load dec-15u.rim 77637
- Verify that the bootstrap loaded correctly:
sim> ex pc
PC: 077646
- Mount the Advanced Software System DECtape image on DECtape unit 0:
sim> attach dt adss15_32k.dtp
- Run the bootstrap:
sim> run
- The DECtape will boot and print out
KMS9-15 V5B000
$
and is now ready for commands. Recognized commands include:
D list system device directory
I list available commands
R list device assignments
SCOM list systems communication region
- To run Focal, assign unused DAT slot 10 and then load Focal
$A LPA0 10
$GLOAD
LOADER V5B000
>_FOCAL<altmode = control-[>
FOCAL V9A
*TYPE 2+2,!
4.0000
*
10. PDP-10 TOPS-10 7.03, TOPS-20 V4.1
TOPS-10 was the primary time-shared operating system for the PDP-10.
Installation and distribution tapes for TOPS-10 7.03 are available at
http://pdp-10.trailing-edge.com.
TOPS-20 was a popular alternative derived from the BBN TENEX system.
Installation and distribution tapes for TOPS-10 7.03 and TOPS-20 4.1
are available at http://pdp-10.trailing-edge.com.
[end simh_swre.txt]