1
0
mirror of https://github.com/simh/simh.git synced 2026-03-22 17:07:51 +00:00

simh v3.12-2

This commit is contained in:
Bob Supnik
2022-06-17 09:03:47 -07:00
committed by Mark Pizzolato
parent b0568dc2cb
commit 14dccaa4e7
8 changed files with 1574 additions and 380 deletions

View File

@@ -1,6 +1,6 @@
/* id_fd.c: Interdata floppy disk simulator
Copyright (c) 2001-2013, Robert M Supnik
Copyright (c) 2001-2021, Robert M Supnik
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
@@ -25,6 +25,7 @@
fd M46-630 floppy disk
31-Jan-21 RMS Revised for new register macros
03-Sep-13 RMS Added explicit void * cast
19-Mar-12 RMS Fixed macro naming conflict (Mark Pizzolato)
@@ -169,7 +170,7 @@ REG fd_reg[] = {
{ HRDATA (STA, fd_sta, 8) },
{ HRDATA (BUF, fd_db, 8) },
{ HRDATA (LRN, fd_lrn, 16) },
{ BRDATA (ESTA, fd_es, 16, 8, ES_SIZE * FD_NUMDR) },
{ CRDATA (ESTA, fd_es, 16, 8, ES_SIZE * FD_NUMDR) },
{ BRDATA (DBUF, fdxb, 16, 8, FD_NUMBY) },
{ HRDATA (DBPTR, fd_bptr, 8) },
{ FLDATA (WDV, fd_wdv, 0) },

View File

@@ -1,6 +1,6 @@
/* pdp11_rq.c: MSCP disk controller simulator
Copyright (c) 2002-2018, Robert M Supnik
Copyright (c) 2002-2022, Robert M Supnik
Derived from work by Stephen F. Shirron
Permission is hereby granted, free of charge, to any person obtaining a
@@ -26,6 +26,8 @@
rq RQDX3 disk controller
06=Mar-22 RMS Added more disk types (Mark Pizzolato)
31-Jan-21 RMS Revised for new register macros
28-May-18 RMS Changed to avoid nested comment warnings (Mark Pizzolato)
23-Oct-13 RMS Revised for new boot setup routine
17-Mar-13 RMS Fixed bug in ABORT link walk loop (Dave Bryan)
@@ -249,6 +251,7 @@ x RA73 70(+1) 21 2667+ 21 1 ? 3920490
#define RQDF_RMV 01 /* removable */
#define RQDF_RO 02 /* read only */
#define RQDF_SDI 04 /* SDI drive */
#define RQDF_DSSI 010 /* DSSI drive */
#define RX50_DTYPE 0
#define RX50_SECT 10
@@ -525,6 +528,160 @@ x RA73 70(+1) 21 2667+ 21 1 ? 3920490
#define RD32_MED 0x25644020
#define RD32_FLGS 0
/* Below here, imported from V4 */
#define RC25_DTYPE 17 /* */
#define RC25_SECT 50 /* */
#define RC25_SURF 8
#define RC25_CYL 1260 /* */
#define RC25_TPG RC25_SURF
#define RC25_GPC 1
#define RC25_XBN 0 /* */
#define RC25_DBN 0 /* */
#define RC25_LBN 50902 /* ? 50*8*1260 ? */
#define RC25_RCTS 0 /* */
#define RC25_RCTC 1
#define RC25_RBN 0 /* */
#define RC25_MOD 2
#define RC25_MED 0x20643019
#define RC25_FLGS RQDF_RMV
#define RCF25_DTYPE 18 /* */
#define RCF25_SECT 50 /* */
#define RCF25_SURF 8
#define RCF25_CYL 1260 /* */
#define RCF25_TPG RCF25_SURF
#define RCF25_GPC 1
#define RCF25_XBN 0 /* */
#define RCF25_DBN 0 /* */
#define RCF25_LBN 50902 /* ? 50*8*1260 ? */
#define RCF25_RCTS 0 /* */
#define RCF25_RCTC 1
#define RCF25_RBN 0 /* */
#define RCF25_MOD 3
#define RCF25_MED 0x20643319
#define RCF25_FLGS 0
#define RA80_DTYPE 19 /* SDI drive */
#define RA80_SECT 31 /* +1 spare/track */
#define RA80_SURF 14
#define RA80_CYL 546 /* */
#define RA80_TPG RA80_SURF
#define RA80_GPC 1
#define RA80_XBN 0 /* */
#define RA80_DBN 0 /* */
#define RA80_LBN 237212 /* 31*14*546 */
#define RA80_RCTS 0 /* */
#define RA80_RCTC 1
#define RA80_RBN 0 /* */
#define RA80_MOD 1
#define RA80_MED 0x25641050
#define RA80_FLGS RQDF_SDI
// [RLA] Most of these RA70 parameters came from doing a DUSTAT on a real
// [RLA] RA70 drive. The remainder are just educated guesses...
#define RA70_DTYPE 20 /* SDI drive */
#define RA70_SECT 33 /* +1 spare/track */
#define RA70_SURF 11 /* tracks/cylinder */
#define RA70_CYL 1507 /* 0-1506 user */
#define RA70_TPG RA70_SURF
#define RA70_GPC 1
#define RA70_XBN 0 /* ??? */
#define RA70_DBN 0 /* ??? */
#define RA70_LBN 547041 /* 33*11*1507 */
#define RA70_RCTS 198 /* Size of the RCT */
#define RA70_RCTC 7 /* Number of RCT copies */
#define RA70_RBN 16577 /* 1*11*1507 */
#define RA70_MOD 18
#define RA70_MED 0x25641046 /* RA70 MEDIA ID */
#define RA70_FLGS RQDF_SDI
// [RLA] Likewise for the RA73 ...
#define RA73_DTYPE 21 /* SDI drive */
#define RA73_SECT 70 /* +1 spare/track */
#define RA73_SURF 21 /* tracks/cylinder */
#define RA73_CYL 2667 /* 0-2666 user */
#define RA73_TPG RA73_SURF
#define RA73_GPC 1
#define RA73_XBN 0 /* ??? */
#define RA73_DBN 0 /* ??? */
#define RA73_LBN 3920490 /* 70*21*2667 */
#define RA73_RCTS 198 /* Size of the RCT ??????*/
#define RA73_RCTC 7 /* Number of RCT copies */
#define RA73_RBN 56007 /* 1*21*2667 */
#define RA73_MOD 47
#define RA73_MED 0x25641049 /* RA73 MEDIA ID */
#define RA73_FLGS RQDF_SDI
/* The RF drives don't have any useful error parameters. */
/* These entries are derived from basic geometry and size */
/* info in Ultrix 4.5 disktab entries. */
#define RF30_DTYPE 22 /* DSSI drive */
#define RF30_SECT 37 /* +1 spare/track */
#define RF30_SURF 6
#define RF30_CYL 1320 /* 0-1914 user */
#define RF30_TPG RF30_SURF
#define RF30_GPC 1
#define RF30_XBN 1456 /* cyl 1917-1918? */
#define RF30_DBN 1456 /* cyl 1919-1920? */
#define RF30_LBN 293040 /* 37*6*1320 */
#define RF30_RCTS 1428 /* cyl 1915-1916? */
#define RF30_RCTC 1
#define RF30_RBN 26810 /* 1 *14*1915 */
#define RF30_MOD 21
#define RF30_MED 0x2264601E
#define RF30_FLGS RQDF_DSSI
#define RF31_DTYPE 23 /* DSSI drive */
#define RF31_SECT 50 /* +1 spare/track */
#define RF31_SURF 8
#define RF31_CYL 1861 /* 0-1860 user */
#define RF31_TPG RF31_SURF
#define RF31_GPC 1
#define RF31_XBN 1456 /* cyl 1917-1918? */
#define RF31_DBN 1456 /* cyl 1919-1920? */
#define RF31_LBN 744400 /* 50*8*1861 */
#define RF31_RCTS 1428 /* cyl 1915-1916? */
#define RF31_RCTC 1
#define RF31_RBN 26810 /* 1 *14*1915 */
#define RF31_MOD 27
#define RF31_MED 0x2264601F
#define RF31_FLGS RQDF_DSSI
#define RF71_DTYPE 24 /* DSSI drive */
#define RF71_SECT 37 /* +1 spare/track */
#define RF71_SURF 16
#define RF71_CYL 1320 /* 0-1914 user */
#define RF71_TPG RF71_SURF
#define RF71_GPC 1
#define RF71_XBN 1456 /* cyl 1917-1918? */
#define RF71_DBN 1456 /* cyl 1919-1920? */
#define RF71_LBN 781440 /* 37*16*1320 */
#define RF71_RCTS 1428 /* cyl 1915-1916? */
#define RF71_RCTC 1
#define RF71_RBN 26810 /* 1 *14*1915 */
#define RF71_MOD 40
#define RF71_MED 0x22646047
#define RF71_FLGS RQDF_DSSI
#define RF72_DTYPE 25 /* DSSI drive */
#define RF72_SECT 50 /* +1 spare/track */
#define RF72_SURF 21
#define RF72_CYL 1861 /* 0-1860 user */
#define RF72_TPG RF72_SURF
#define RF72_GPC 1
#define RF72_XBN 1456 /* cyl 1917-1918? */
#define RF72_DBN 1456 /* cyl 1919-1920? */
#define RF72_LBN 1954050 /* 50*21*1861 */
#define RF72_RCTS 1428 /* cyl 1915-1916? */
#define RF72_RCTC 1
#define RF72_RBN 26810 /* 1 *14*1915 */
#define RF72_MOD 28
#define RF72_MED 0x22646048
#define RF72_FLGS RQDF_DSSI
struct drvtyp {
int32 sect; /* sectors */
int32 surf; /* surfaces */
@@ -551,15 +708,87 @@ struct drvtyp {
#define RQ_SIZE(d) (d##_LBN * RQ_NUMBY)
static struct drvtyp drv_tab[] = {
{ RQ_DRV (RX50), "RX50" }, { RQ_DRV (RX33), "RX33" },
{ RQ_DRV (RD51), "RD51" }, { RQ_DRV (RD31), "RD31" },
{ RQ_DRV (RD52), "RD52" }, { RQ_DRV (RD53), "RD53" },
{ RQ_DRV (RD54), "RD54" }, { RQ_DRV (RA82), "RA82" },
{ RQ_DRV (RRD40), "RRD40" }, { RQ_DRV (RA72), "RA72" },
{ RQ_DRV (RA90), "RA90" }, { RQ_DRV (RA92), "RA92" },
{ RQ_DRV (RA8U), "RAUSER" }, { RQ_DRV (RA60), "RA60" },
{ RQ_DRV (RA81), "RA81" }, { RQ_DRV (RA71), "RA71" },
{ RQ_DRV (RX50), "RX50" },
{ RQ_DRV (RX33), "RX33" },
{ RQ_DRV (RD51), "RD51" },
{ RQ_DRV (RD31), "RD31" },
{ RQ_DRV (RD52), "RD52" },
{ RQ_DRV (RD53), "RD53" },
{ RQ_DRV (RD54), "RD54" },
{ RQ_DRV (RA82), "RA82" },
{ RQ_DRV (RRD40), "RRD40" },
{ RQ_DRV (RA72), "RA72" },
{ RQ_DRV (RA90), "RA90" },
{ RQ_DRV (RA92), "RA82" },
{ RQ_DRV (RA8U), "RAUSER" },
{ RQ_DRV (RA60), "RA60" },
{ RQ_DRV (RA81), "RA81" },
{ RQ_DRV (RA71), "RA71" },
{ RQ_DRV (RD32), "RD32" },
{ RQ_DRV (RC25), "RC25" },
{ RQ_DRV (RCF25), "RCF25" },
{ RQ_DRV (RA80), "RA80" },
{ RQ_DRV (RA70), "RA70" },
{ RQ_DRV (RA73), "RA73" },
{ RQ_DRV (RF30), "RF30" },
{ RQ_DRV (RF31), "RF31" },
{ RQ_DRV (RF71), "RF71" },
{ RQ_DRV (RF72), "RF72" },
{ 0 }
};
/* Controller parameters */
#define DEFAULT_CTYPE 0
// AFAIK the UNIBUS KLESI and QBUS KLESI used the same controller type...
#define KLESI_CTYPE 1 // RC25 controller (UNIBUS and QBUS both)
#define KLESI_UQPM 1
#define KLESI_MODEL 1
#define RUX50_CTYPE 2 // UNIBUS RX50-only controller
#define RUX50_UQPM 2
#define RUX50_MODEL 2
#define UDA50_CTYPE 3 // UNIBUS SDI (RAxx) controller
#define UDA50_UQPM 6
#define UDA50_MODEL 6
#define RQDX3_CTYPE 4 // QBUS RX50/RDxx controller
#define RQDX3_UQPM 19
#define RQDX3_MODEL 19
#define KDA50_CTYPE 5 // QBUS SDI (RAxx) controller
#define KDA50_UQPM 13
#define KDA50_MODEL 13
#define KRQ50_CTYPE 6 // QBUS RRD40/50 CDROM controller
#define KRQ50_UQPM 16
#define KRQ50_MODEL 16
#define KRU50_CTYPE 7 // UNIBUS RRD40/50 CDROM controller
#define KRU50_UQPM 26
#define KRU50_MODEL 26
struct ctlrtyp {
uint32 uqpm; /* port model */
uint16 model; /* controller model */
const char *name; /* name */
};
#define RQ_CTLR(d) \
d##_UQPM, d##_MODEL
static struct ctlrtyp ctlr_tab[] = {
{ 0, 0, "DEFAULT" },
{ RQ_CTLR (KLESI), "KLESI" },
{ RQ_CTLR (RUX50), "RUX50" },
{ RQ_CTLR (UDA50), "UDA50" },
{ RQ_CTLR (RQDX3), "RQDX3" },
{ RQ_CTLR (KDA50), "KDA50" },
{ RQ_CTLR (KRQ50), "KRQ50" },
{ RQ_CTLR (KRU50), "KRU50" },
{ 0 }
};
@@ -592,6 +821,7 @@ typedef struct {
uint32 credits; /* credits */
uint32 hat; /* host timer */
uint32 htmo; /* host timeout */
// uint32 ctype; /* controller type */
struct uq_ring cq; /* cmd ring */
struct uq_ring rq; /* rsp ring */
struct rqpkt pak[RQ_NPKTS]; /* packet queue */
@@ -708,7 +938,7 @@ REG rq_reg[] = {
{ DRDATA (I4TIME, rq_itime4, 24), PV_LEFT + REG_NZ },
{ DRDATA (QTIME, rq_qtime, 24), PV_LEFT + REG_NZ },
{ DRDATA (XTIME, rq_xtime, 24), PV_LEFT + REG_NZ },
{ BRDATA (PKTS, rq_ctx.pak, DEV_RDX, 16, RQ_NPKTS * (RQ_PKT_SIZE_W + 1)) },
{ XRDATA (PKTS, rq_ctx.pak, DEV_RDX, 16, 0, RQ_NPKTS * (RQ_PKT_SIZE_W + 1), sizeof (int16), sizeof (int16)) },
{ URDATA (CPKT, rq_unit[0].cpkt, 10, 5, 0, RQ_NUMDR, 0) },
{ URDATA (PKTQ, rq_unit[0].pktq, 10, 5, 0, RQ_NUMDR, 0) },
{ URDATA (UFLG, rq_unit[0].uf, DEV_RDX, 16, 0, RQ_NUMDR, 0) },
@@ -754,6 +984,8 @@ MTAB rq_mod[] = {
&rq_set_type, NULL, NULL },
{ MTAB_XTD | MTAB_VUN, RA60_DTYPE, NULL, "RA60",
&rq_set_type, NULL, NULL },
{ MTAB_XTD | MTAB_VUN, RA80_DTYPE, NULL, "RA80",
&rq_set_type, NULL, NULL },
{ MTAB_XTD | MTAB_VUN, RA81_DTYPE, NULL, "RA81",
&rq_set_type, NULL, NULL },
{ MTAB_XTD | MTAB_VUN, RA82_DTYPE, NULL, "RA82",
@@ -762,16 +994,32 @@ MTAB rq_mod[] = {
&rq_set_type, NULL, NULL },
{ MTAB_XTD | MTAB_VUN, RRD40_DTYPE, NULL, "CDROM",
&rq_set_type, NULL, NULL },
{ MTAB_XTD | MTAB_VUN, RA70_DTYPE, NULL, "RA70",
&rq_set_type, NULL, NULL },
{ MTAB_XTD | MTAB_VUN, RA71_DTYPE, NULL, "RA71",
&rq_set_type, NULL, NULL },
{ MTAB_XTD | MTAB_VUN, RA72_DTYPE, NULL, "RA72",
&rq_set_type, NULL, NULL },
{ MTAB_XTD | MTAB_VUN, RA73_DTYPE, NULL, "RA73",
&rq_set_type, NULL, NULL },
{ MTAB_XTD | MTAB_VUN, RA90_DTYPE, NULL, "RA90",
&rq_set_type, NULL, NULL },
{ MTAB_XTD | MTAB_VUN, RA92_DTYPE, NULL, "RA92",
&rq_set_type, NULL, NULL },
{ MTAB_XTD | MTAB_VUN, RA8U_DTYPE, NULL, "RAUSER",
&rq_set_type, NULL, NULL },
{ MTAB_XTD | MTAB_VUN, RC25_DTYPE, NULL, "RC25",
&rq_set_type, NULL, NULL },
{ MTAB_XTD | MTAB_VUN, RCF25_DTYPE, NULL, "RCF25",
&rq_set_type, NULL, NULL },
{ MTAB_XTD | MTAB_VUN, RF30_DTYPE, NULL, "RF30",
&rq_set_type, NULL, NULL },
{ MTAB_XTD | MTAB_VUN, RF31_DTYPE, NULL, "RF31",
&rq_set_type, NULL, NULL },
{ MTAB_XTD | MTAB_VUN, RA8U_DTYPE, NULL, "RAUSER",
&rq_set_type, NULL, NULL },
{ MTAB_XTD | MTAB_VUN, RA8U_DTYPE, NULL, "RA8U",
&rq_set_type, NULL, NULL },
{ MTAB_XTD | MTAB_VUN, 0, "TYPE", NULL,
NULL, &rq_show_type, NULL },
#if defined (VM_PDP11)
@@ -847,7 +1095,7 @@ REG rqb_reg[] = {
{ FLDATA (PRGI, rqb_ctx.prgi, 0), REG_HIDDEN },
{ FLDATA (PIP, rqb_ctx.pip, 0), REG_HIDDEN },
{ FLDATA (INT, rqb_ctx.irq, 0) },
{ BRDATA (PKTS, rqb_ctx.pak, DEV_RDX, 16, RQ_NPKTS * (RQ_PKT_SIZE_W + 1)) },
{ XRDATA (PKTS, rqb_ctx.pak, DEV_RDX, 16, 0, RQ_NPKTS * (RQ_PKT_SIZE_W + 1), sizeof (int16), sizeof (int16)) },
{ URDATA (CPKT, rqb_unit[0].cpkt, 10, 5, 0, RQ_NUMDR, 0) },
{ URDATA (PKTQ, rqb_unit[0].pktq, 10, 5, 0, RQ_NUMDR, 0) },
{ URDATA (UFLG, rqb_unit[0].uf, DEV_RDX, 16, 0, RQ_NUMDR, 0) },
@@ -916,7 +1164,7 @@ REG rqc_reg[] = {
{ FLDATA (PRGI, rqc_ctx.prgi, 0), REG_HIDDEN },
{ FLDATA (PIP, rqc_ctx.pip, 0), REG_HIDDEN },
{ FLDATA (INT, rqc_ctx.irq, 0) },
{ BRDATA (PKTS, rqc_ctx.pak, DEV_RDX, 16, RQ_NPKTS * (RQ_PKT_SIZE_W + 1)) },
{ XRDATA (PKTS, rqc_ctx.pak, DEV_RDX, 16, 0, RQ_NPKTS * (RQ_PKT_SIZE_W + 1), sizeof (int16), sizeof (int16)) },
{ URDATA (CPKT, rqc_unit[0].cpkt, 10, 5, 0, RQ_NUMDR, 0) },
{ URDATA (PKTQ, rqc_unit[0].pktq, 10, 5, 0, RQ_NUMDR, 0) },
{ URDATA (UFLG, rqc_unit[0].uf, DEV_RDX, 16, 0, RQ_NUMDR, 0) },
@@ -985,7 +1233,7 @@ REG rqd_reg[] = {
{ FLDATA (PRGI, rqd_ctx.prgi, 0), REG_HIDDEN },
{ FLDATA (PIP, rqd_ctx.pip, 0), REG_HIDDEN },
{ FLDATA (INT, rqd_ctx.irq, 0) },
{ BRDATA (PKTS, rqd_ctx.pak, DEV_RDX, 16, RQ_NPKTS * (RQ_PKT_SIZE_W + 1)) },
{ XRDATA (PKTS, rqd_ctx.pak, DEV_RDX, 16, 0, RQ_NPKTS * (RQ_PKT_SIZE_W + 1), sizeof (int16), sizeof (int16)) },
{ URDATA (CPKT, rqd_unit[0].cpkt, 10, 5, 0, RQ_NUMDR, 0) },
{ URDATA (PKTQ, rqd_unit[0].pktq, 10, 5, 0, RQ_NUMDR, 0) },
{ URDATA (UFLG, rqd_unit[0].uf, DEV_RDX, 16, 0, RQ_NUMDR, 0) },

Binary file not shown.

Binary file not shown.

1074
makefile

File diff suppressed because it is too large Load Diff

273
scp.c
View File

@@ -1,6 +1,6 @@
/* scp.c: simulator control program
Copyright (c) 1993-2020, Robert M Supnik
Copyright (c) 1993-2022, 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"),
@@ -23,7 +23,17 @@
used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from Robert M Supnik.
06-Mar-22 RMS Removed UNIT_RAW support
21-Oct-21 RMS Fixed bug in byte deposits if aincr > 1
20=Sep-21 RMS Fixed bug in nested DO recognition (per Mark Pizzolato)
15-Apr-21 RMS Changed RUN to store new PC value both before RESET
(former behavior) and after (per Mark Pizzolato)
18-Mar-21 JDB Revised "attach_unit" and "detach_unit" for pipe support
Modified tests to allow UNIT_RO without UNIT_ROABLE
16-Feb-21 JDB Rewrote get_rval, put_rval to support arrays of structures
01-Feb-21 JDB Added casts for down-conversions
25-Jan-21 JDB REG "size" field now determines access size
REG "maxval" field now determines maximum allowed value
30-Nov-20 RMS Fixed RUN problem if CPU reset clears PC (Mark Pizzolato)
09-Nov-20 RMS Added hack for sim_card multiple attach (Mark Pizzolato)
23-Oct-20 JDB Added tmxr_post_logs calls to flush and close log files
@@ -230,8 +240,9 @@
#include "sim_tmxr.h"
#include <signal.h>
#include <ctype.h>
#include <sys/stat.h>
#if defined(HAVE_DLOPEN) /* Dynamic Readline support */
#if defined(SIM_HAVE_DLOPEN) /* Dynamic Readline support */
#include <dlfcn.h>
#endif
@@ -258,8 +269,6 @@
x = sim_interval
#define SZ_D(dp) (size_map[((dp)->dwidth + CHAR_BIT - 1) / CHAR_BIT])
#define SZ_R(rp) \
(size_map[((rp)->width + (rp)->offset + CHAR_BIT - 1) / CHAR_BIT])
#if defined (USE_INT64)
#define SZ_LOAD(sz,v,mb,j) \
if (sz == sizeof (uint8)) v = *(((uint8 *) mb) + ((uint32) j)); \
@@ -374,7 +383,8 @@ t_stat ex_reg (FILE *ofile, t_value val, int32 flag, REG *rptr, uint32 idx);
t_stat dep_reg (int32 flag, char *cptr, REG *rptr, uint32 idx);
t_stat exdep_addr_loop (FILE *ofile, SCHTAB *schptr, int32 flag, char *cptr,
t_addr low, t_addr high, DEVICE *dptr, UNIT *uptr);
t_stat ex_addr (FILE *ofile, int32 flag, t_addr addr, DEVICE *dptr, UNIT *uptr, int32 dfltinc);
t_stat ex_addr (FILE *ofile, int32 flag, t_addr addr, DEVICE *dptr,
UNIT *uptr, int32 dfltinc);
t_stat dep_addr (int32 flag, char *cptr, t_addr addr, DEVICE *dptr,
UNIT *uptr, int32 dfltinc);
t_stat step_svc (UNIT *ptr);
@@ -1020,7 +1030,7 @@ do {
sim_switches = 0; /* init switches */
isdo = FALSE;
if (cmdp = find_cmd (gbuf)) { /* lookup command */
isdo = (MATCH_CMD (gbuf, "DO") == 0);
isdo = (strcmp (cmdp->name, "DO") == 0);
if (isdo) { /* DO command? */
if (flag >= DO_NEST_LVL) /* nest too deep? */
stat = SCPE_NEST;
@@ -1374,8 +1384,9 @@ if (cptr)
if (uptr == NULL)
return SCPE_NOFNC;
if (((uptr->flags & UNIT_SEQ) == 0) || /* must be sequential, */
((uptr->flags & UNIT_ROABLE) != 0) || /* not RO settable */
((uptr->flags & UNIT_MUSTBUF) != 0)) /* not buffered */
((uptr->flags & (UNIT_RO | UNIT_ROABLE)) != 0) || /* not RO settable */
((uptr->flags & UNIT_MUSTBUF) != 0) || /* not buffered */
((uptr->dynflags & UNIT_PIPE) != 0)) /* not a pipe */
return SCPE_NOFNC;
if ((uptr->flags & UNIT_ATT) == 0) /* must be attached */
return SCPE_UNATT;
@@ -2127,9 +2138,21 @@ return attach_unit (uptr, cptr); /* no, std routine */
/* Attach unit to file */
#if !defined (S_ISFIFO)
#if !defined (S_IFMT) && defined (_S_IFMT)
#define S_IFMT _S_IFMT
#endif
#if defined (_S_IFIFO)
#define S_ISFIFO(m) (((m) & S_IFMT) == _S_IFIFO)
#else
#define S_ISFIFO(m) 0
#endif
#endif
t_stat attach_unit (UNIT *uptr, char *cptr)
{
DEVICE *dptr;
struct stat info;
if (!(uptr->flags & UNIT_ATTABLE)) /* not attachable? */
return SCPE_NOATT;
@@ -2141,8 +2164,24 @@ uptr->filename = (char *) calloc (CBUFSIZE, sizeof (char)); /* alloc name buf */
if (uptr->filename == NULL)
return SCPE_MEM;
strncpy (uptr->filename, cptr, CBUFSIZE); /* save name */
if (sim_switches & SWMASK ('R')) { /* read only? */
if ((uptr->flags & UNIT_ROABLE) == 0) /* allowed? */
if ((!stat (cptr, &info)) && S_ISFIFO (info.st_mode)) /* if file exists and is a pipe */
if (uptr->flags & UNIT_SEQ) { /* then if the unit is sequential */
if (uptr->flags & (UNIT_RO | UNIT_ROABLE)) /* if the unit is readable */
uptr->fileref = sim_fopen (cptr, "rb"); /* then open the pipe for reading */
else /* otherwise */
uptr->fileref = sim_fopen (cptr, "wb"); /* open the pipe for writing */
if (uptr->fileref == NULL) /* if the file failed to open */
return attach_err (uptr, SCPE_OPENERR); /* then report the error */
else /* otherwise */
uptr->dynflags = uptr->dynflags | UNIT_PIPE; /* set the pipe flag */
}
else /* otherwise the unit is not sequential */
return SCPE_NOFNC; /* so it cannot be attached to a pipe */
else if (sim_switches & SWMASK ('R')) { /* read only? */
if ((uptr->flags & (UNIT_RO | UNIT_ROABLE)) == 0) /* allowed? */
return attach_err (uptr, SCPE_NORO); /* no, error */
uptr->fileref = sim_fopen (cptr, "rb"); /* open rd only */
if (uptr->fileref == NULL) /* open fail? */
@@ -2152,18 +2191,18 @@ if (sim_switches & SWMASK ('R')) { /* read only? */
sim_printf ("%s: unit is read only\n", sim_dname (dptr));
}
else if (sim_switches & SWMASK ('N')) { /* new file only? */
uptr->fileref = sim_fopen (cptr, "wb+"); /* open new file */
if (uptr->fileref == NULL) /* open fail? */
return attach_err (uptr, SCPE_OPENERR); /* yes, error */
if (!sim_quiet)
sim_printf ("%s: creating new file\n", sim_dname (dptr));
uptr->fileref = sim_fopen (cptr, "wb+"); /* open new file */
if (uptr->fileref == NULL) /* open fail? */
return attach_err (uptr, SCPE_OPENERR); /* yes, error */
if (!sim_quiet)
sim_printf ("%s: creating new file\n", sim_dname (dptr));
}
else { /* normal */
uptr->fileref = sim_fopen (cptr, "rb+"); /* open r/w */
if (uptr->fileref == NULL) { /* open fail? */
if ((errno == EROFS) || (errno == EACCES)) { /* read only? */
if ((uptr->flags & UNIT_ROABLE) == 0) /* allowed? */
return attach_err (uptr, SCPE_NORO); /* no error */
if ((uptr->flags & (UNIT_RO | UNIT_ROABLE)) == 0) /* allowed? */
return attach_err (uptr, SCPE_NORO); /* no error */
uptr->fileref = sim_fopen (cptr, "rb"); /* open rd only */
if (uptr->fileref == NULL) /* open fail? */
return attach_err (uptr, SCPE_OPENERR); /* yes, error */
@@ -2316,6 +2355,7 @@ if ((uptr->flags & UNIT_BUF) && (uptr->filebuf)) { /* buffered? */
}
uptr->flags = uptr->flags & ~(UNIT_ATT | /* clear ATT */
((uptr->flags & UNIT_ROABLE) ? UNIT_RO : 0)); /* clear RO if dynamic */
uptr->dynflags = uptr->dynflags & ~UNIT_PIPE; /* clear the pipe flag */
free (uptr->filename);
uptr->filename = NULL;
if (fclose (uptr->fileref) == EOF)
@@ -2560,7 +2600,7 @@ void *mbuf;
int32 j, blkcnt, limit, unitno, time, flg;
uint32 us, depth;
t_addr k, high, old_capac;
t_value val, mask;
t_value val, max;
t_stat r;
size_t sz;
t_bool v35, v32;
@@ -2732,10 +2772,13 @@ for ( ;; ) { /* device loop */
if (depth != rptr->depth) /* [V2.10+] mismatch? */
sim_printf ("Register depth mismatch: %s %s, file = %d, sim = %d\n",
sim_dname (dptr), buf, depth, rptr->depth);
mask = width_mask[rptr->width]; /* get mask */
if (rptr->maxval > 0) /* if a maximum value is defined */
max = rptr->maxval; /* then use it */
else /* otherwise */
max = width_mask[rptr->width]; /* the mask defines the maximum value */
for (us = 0; us < depth; us++) { /* loop thru values */
READ_I (val); /* read value */
if (val > mask) /* value ok? */
if (val > max) /* value ok? */
sim_printf ("Invalid register value: %s %s\n", sim_dname (dptr), buf);
else if (us < rptr->depth) /* in range? */
put_rval (rptr, us, val);
@@ -2777,14 +2820,17 @@ if ((flag == RU_RUN) || (flag == RU_GO)) { /* run or go */
pcv = sim_vm_parse_addr (sim_dflt_dev, gbuf, &tptr);
else pcv = strtotv (gbuf, &tptr, sim_PC->radix);/* parse PC */
if ((tptr == gbuf) || (*tptr != 0) || /* error? */
(pcv > width_mask[sim_PC->width]))
(pcv > (sim_PC->maxval > 0
? sim_PC->maxval
: width_mask[sim_PC->width])))
return SCPE_ARG;
put_rval (sim_PC, 0, pcv); /* store new PC */
}
if ((flag == RU_RUN) && /* run? */
((r = run_boot_prep ()) != SCPE_OK)) /* reset sim */
return r;
if (new_pcv) /* new PC value? */
put_rval (sim_PC, 0, pcv);
put_rval (sim_PC, 0, pcv); /* store again */
}
else if (flag == RU_STEP) { /* step */
@@ -2830,7 +2876,8 @@ else if (flag != RU_CONT) /* must be cont */
for (i = 1; (dptr = sim_devices[i]) != NULL; i++) { /* reposition all */
for (j = 0; j < dptr->numunits; j++) { /* seq devices */
uptr = dptr->units + j;
if ((uptr->flags & (UNIT_ATT + UNIT_SEQ)) == (UNIT_ATT + UNIT_SEQ))
if ((uptr->flags & (UNIT_ATT + UNIT_SEQ)) == (UNIT_ATT + UNIT_SEQ) &&
(uptr->dynflags & UNIT_PIPE) == 0)
sim_fseek (uptr->fileref, uptr->pos, SEEK_SET);
}
}
@@ -2875,7 +2922,6 @@ for (i = 1; (dptr = sim_devices[i]) != NULL; i++) { /* flush attached files
if ((uptr->flags & UNIT_ATT) && /* attached, */
!(uptr->flags & UNIT_BUF) && /* not buffered, */
(uptr->fileref) && /* real file, */
!(uptr->flags & UNIT_RAW) && /* not raw, */
!(uptr->flags & UNIT_RO)) /* not read only? */
fflush (uptr->fileref);
}
@@ -3155,11 +3201,15 @@ t_stat exdep_addr_loop (FILE *ofile, SCHTAB *schptr, int32 flag, char *cptr,
t_addr i, mask;
t_stat reason, dfltinc;
if (uptr->flags & UNIT_DIS) /* disabled? */
return SCPE_UDIS;
mask = (t_addr) width_mask[dptr->awidth];
if ((low > mask) || (high > mask) || (low > high))
return SCPE_ARG;
dfltinc = parse_sym ("0", 0, uptr, sim_eval, sim_switches);
if (dfltinc > 0) /* parse_sym doing nums? */
dfltinc = 1 - dptr->aincr; /* no, use std dflt incr */
for (i = low; i <= high; ) { /* all paths must incr!! */
reason = get_aval (i, dptr, uptr); /* get data */
if (reason != SCPE_OK) /* return if error */
@@ -3229,43 +3279,50 @@ return SCPE_OK;
idx = index
Outputs:
return = register value
Implementation notes:
1. The stride is the size of the element spacing for arrays, which is
equivalent to the addressing increment for array subscripting. For
scalar registers, the stride will be zero (as will the idx value), so the
access pointer is same as the specified location pointer.
2. The size of the t_value type is determined by the USE_INT64 symbol and
will be either a 32-bit or a 64-bit type. It represents the largest
value that can be returned and so is the default if one of the smaller
sizes is not indicated. If USE_INT64 is not defined, t_value will be
identical to uint32. In this case, compilers are generally smart enough
to eliminate the 32-bit size test and combine the two assignments into a
single default assignment.
*/
t_value get_rval (REG *rptr, uint32 idx)
{
size_t sz;
t_value val;
UNIT *uptr;
void *ptr;
sz = SZ_R (rptr);
if ((rptr->depth > 1) && (rptr->flags & REG_CIRC)) {
idx = idx + rptr->qptr;
if (idx >= rptr->depth) idx = idx - rptr->depth;
if ((rptr->depth > 1) && (rptr->flags & REG_CIRC)) { /* if the register is a circular queue */
idx = idx + rptr->qptr; /* then adjust the index relative to the queue */
if (idx >= rptr->depth) /* if the index is beyond the end of the array */
idx = idx - rptr->depth; /* then wrap it around */
}
if ((rptr->depth > 1) && (rptr->flags & REG_UNIT)) {
uptr = ((UNIT *) rptr->loc) + idx;
#if defined (USE_INT64)
if (sz <= sizeof (uint32))
val = *((uint32 *) uptr);
else val = *((t_uint64 *) uptr);
#else
val = *((uint32 *) uptr);
#endif
}
else if (((rptr->depth > 1) || (rptr->flags & REG_FIT)) &&
(sz == sizeof (uint8)))
val = *(((uint8 *) rptr->loc) + idx);
else if (((rptr->depth > 1) || (rptr->flags & REG_FIT)) &&
(sz == sizeof (uint16)))
val = *(((uint16 *) rptr->loc) + idx);
#if defined (USE_INT64)
else if (sz <= sizeof (uint32))
val = *(((uint32 *) rptr->loc) + idx);
else val = *(((t_uint64 *) rptr->loc) + idx);
#else
else val = *(((uint32 *) rptr->loc) + idx);
#endif
val = (val >> rptr->offset) & width_mask[rptr->width];
ptr = ((char *) rptr->loc) + (idx * rptr->stride); /* point at the starting byte of the item */
if (rptr->size == sizeof (uint8)) /* get the value */
val = *((uint8 *) ptr); /* using a size */
/* appropriate to */
else if (rptr->size == sizeof (uint16)) /* the size of */
val = *((uint16 *) ptr); /* the underlying type */
else if (rptr->size == sizeof (uint32))
val = *((uint32 *) ptr);
else /* if the element size is non-standard */
val = *((t_value *) ptr); /* then access using the largest size permitted */
val = (val >> rptr->offset) & width_mask[rptr->width]; /* shift and mask to obtain the final value */
return val;
}
@@ -3283,7 +3340,7 @@ return val;
t_stat dep_reg (int32 flag, char *cptr, REG *rptr, uint32 idx)
{
t_stat r;
t_value val, mask;
t_value val, max;
int32 rdx;
char *tptr, gbuf[CBUFSIZE];
@@ -3300,17 +3357,20 @@ if (flag & EX_I) {
if (*cptr == 0) /* success */
return SCPE_OK;
}
mask = width_mask[rptr->width];
if (rptr->maxval > 0) /* if a maximum value is defined */
max = rptr->maxval; /* then use it */
else /* otherwise */
max = width_mask[rptr->width]; /* the mask defines the maximum value */
GET_RADIX (rdx, rptr->radix);
if ((rptr->flags & REG_VMAD) && sim_vm_parse_addr) { /* address form? */
val = sim_vm_parse_addr (sim_dflt_dev, cptr, &tptr);
if ((tptr == cptr) || (*tptr != 0) || (val > mask))
if ((tptr == cptr) || (*tptr != 0) || (val > max))
return SCPE_ARG;
}
else if (!(rptr->flags & REG_VMFLAGS) || /* dont use sym? */
(parse_sym (cptr, (rptr->flags & REG_UFMASK) | rdx, NULL,
&val, sim_switches | SIM_SW_REG) > SCPE_OK)) {
val = get_uint (cptr, rdx, mask, &r);
val = get_uint (cptr, rdx, max, &r);
if (r != SCPE_OK)
return SCPE_ARG;
}
@@ -3326,59 +3386,54 @@ return SCPE_OK;
rptr = pointer to register descriptor
idx = index
val = new value
mask = mask
Outputs:
none
Implementation notes:
1. mask and val are of type t_value, so an explicit cast is not needed for
that type of assignment.
2. See the notes for the get_rval routine for additional information
regarding the stride calculation and the t_value default assignment,
*/
void put_rval (REG *rptr, uint32 idx, t_value val)
{
size_t sz;
t_value mask;
UNIT *uptr;
void *ptr;
#define PUT_RVAL(sz,rp,id,v,m) \
*(((sz *) rp->loc) + id) = \
(*(((sz *) rp->loc) + id) & \
~((m) << (rp)->offset)) | ((v) << (rp)->offset)
if (rptr == sim_PC) /* if the PC is changing */
sim_brk_npc (0); /* then notify the breakpoint package */
if (rptr == sim_PC)
sim_brk_npc (0);
sz = SZ_R (rptr);
mask = width_mask[rptr->width];
if ((rptr->depth > 1) && (rptr->flags & REG_CIRC)) {
idx = idx + rptr->qptr;
if (idx >= rptr->depth)
idx = idx - rptr->depth;
mask = ~(width_mask [rptr->width] << rptr->offset); /* set up a mask to produce a hole in the element */
val = val << rptr->offset; /* and position the new value to fit the hole */
if ((rptr->depth > 1) && (rptr->flags & REG_CIRC)) { /* if the register is a circular queue */
idx = idx + rptr->qptr; /* then adjust the index relative to the queue */
if (idx >= rptr->depth) /* if the index is beyond the end of the array */
idx = idx - rptr->depth; /* then wrap it around */
}
if ((rptr->depth > 1) && (rptr->flags & REG_UNIT)) {
uptr = ((UNIT *) rptr->loc) + idx;
#if defined (USE_INT64)
if (sz <= sizeof (uint32))
*((uint32 *) uptr) = (*((uint32 *) uptr) &
~(((uint32) mask) << rptr->offset)) |
(((uint32) val) << rptr->offset);
else *((t_uint64 *) uptr) = (*((t_uint64 *) uptr)
& ~(mask << rptr->offset)) | (val << rptr->offset);
#else
*((uint32 *) uptr) = (*((uint32 *) uptr) &
~(((uint32) mask) << rptr->offset)) |
(((uint32) val) << rptr->offset);
#endif
}
else if (((rptr->depth > 1) || (rptr->flags & REG_FIT)) &&
(sz == sizeof (uint8)))
PUT_RVAL (uint8, rptr, idx, (uint32) val, (uint32) mask);
else if (((rptr->depth > 1) || (rptr->flags & REG_FIT)) &&
(sz == sizeof (uint16)))
PUT_RVAL (uint16, rptr, idx, (uint32) val, (uint32) mask);
#if defined (USE_INT64)
else if (sz <= sizeof (uint32))
PUT_RVAL (uint32, rptr, idx, (int32) val, (uint32) mask);
else PUT_RVAL (t_uint64, rptr, idx, val, mask);
#else
else PUT_RVAL (uint32, rptr, idx, val, mask);
#endif
ptr = ((char *) rptr->loc) + (idx * rptr->stride); /* point at the starting byte of the item */
if (rptr->size == sizeof (uint8)) /* store the value */
*((uint8 *) ptr) = /* using a size */
(uint8) (*((uint8 *) ptr) & mask | val); /* appropriate to */
/* the size of */
else if (rptr->size == sizeof (uint16)) /* the underlying type */
*((uint16 *) ptr) =
(uint16) (*((uint16 *) ptr) & mask | val);
else if (rptr->size == sizeof (uint32))
*((uint32 *) ptr) =
(uint32) (*((uint32 *) ptr) & mask | val);
else /* if the element size is non-standard */
*((t_value *) ptr) = /* then access using the largest size permitted */
*((t_value *) ptr) & mask | val;
return;
}
@@ -3411,7 +3466,7 @@ if (!(flag & EX_E))
GET_RADIX (rdx, dptr->dradix);
if ((reason = fprint_sym (ofile, addr, sim_eval, uptr, sim_switches)) > 0) {
fprint_val (ofile, sim_eval[0], rdx, dptr->dwidth, PV_RZRO);
return dfltinc;
reason = dfltinc;
}
if (flag & EX_I)
fprintf (ofile, "\t");
@@ -3452,8 +3507,8 @@ for (i = 0, j = addr; i < sim_emax; i++, j = j + dptr->aincr) {
else {
if (!(uptr->flags & UNIT_ATT))
return SCPE_UNATT;
if (((uptr->flags & UNIT_RAW) != 0) ||
(uptr->fileref == NULL))
if ((uptr->fileref == NULL) ||
((uptr->dynflags & UNIT_PIPE) != 0))
return SCPE_NOFNC;
if (((uptr->flags & UNIT_FIX) != 0) &&
(j >= uptr->capac)) {
@@ -3545,7 +3600,7 @@ for (i = 0, j = addr; i < count; i++, j = j + dptr->aincr) {
else {
if (!(uptr->flags & UNIT_ATT))
return SCPE_UNATT;
if (uptr->flags & UNIT_RAW)
if (uptr->dynflags & UNIT_PIPE)
return SCPE_NOFNC;
if ((uptr->flags & UNIT_FIX) && (j >= uptr->capac))
return SCPE_NXM;
@@ -3641,7 +3696,7 @@ return read_line_p (NULL, cptr, size, stream);
char *read_line_p (char *prompt, char *cptr, int32 size, FILE *stream)
{
char *tptr;
#if defined(HAVE_DLOPEN)
#if defined(SIM_HAVE_DLOPEN)
static int initialized = 0;
static char *(*p_readline)(const char *) = NULL;
static void (*p_add_history)(const char *) = NULL;
@@ -3705,7 +3760,7 @@ while (isspace (*cptr)) /* trim leading spc */
if (*cptr == ';') /* ignore comment */
*cptr = 0;
#if defined (HAVE_DLOPEN)
#if defined (SIM_HAVE_DLOPEN)
if (prompt && p_add_history && *cptr) /* Save non blank lines in history */
p_add_history (cptr);
#endif
@@ -3730,7 +3785,7 @@ char *get_glyph_gen (char *iptr, char *optr, char mchar, t_bool uc)
{
while ((isspace (*iptr) == 0) && (*iptr != 0) && (*iptr != mchar)) {
if (islower (*iptr) && uc)
*optr = toupper (*iptr);
*optr = (char) toupper (*iptr);
else *optr = *iptr;
iptr++; optr++;
}
@@ -4528,7 +4583,7 @@ do {
d = d - 1;
digit = (int32) (val % radix);
val = val / radix;
dbuf[d] = (digit <= 9)? '0' + digit: 'A' + (digit - 10);
dbuf[d] = (char) ((digit <= 9)? '0' + digit: 'A' + (digit - 10));
} while ((d > 0) && (val != 0));
if (format != PV_LEFT) {

View File

@@ -1,6 +1,6 @@
/* sim_defs.h: simulator definitions
Copyright (c) 1993-2020, Robert M Supnik
Copyright (c) 1993-2022, 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"),
@@ -23,6 +23,13 @@
used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from Robert M Supnik.
10-Mar-22 JDB Modified REG macros to fix "stringizing" problem
12-Nov-21 JDB Added UNIT_EXTEND dynamic flag
17-Mar-21 JDB Added UNIT_PIPE dynamic flag
16-Feb-21 JDB Added "stride" to REG to support arrays of structures
Modified REG macros to initialize strides
21-Jan-21 JDB Added "size" and "maxval" fields to the REG structure
Modified REG macros to initialize access sizes
09-Nov-20 RMS More V4.X compatibility hooks (Mark Pizzolato)
26-Oct-19 RMS Removed MTAB_VAL definition
23-Jun-17 RMS Added #include sim_rev.h (Mark Pizzolato)
@@ -137,7 +144,7 @@ typedef signed short int16;
typedef signed int int32;
typedef unsigned char uint8;
typedef unsigned short uint16;
typedef unsigned int uint32;
typedef unsigned int uint32;
typedef int t_stat; /* status */
typedef int t_bool; /* boolean */
@@ -417,11 +424,13 @@ struct sim_unit {
#define UNIT_UFMASK (((1u << UNIT_V_RSV) - 1) & ~((1u << UNIT_V_UF) - 1))
#define UNIT_RFLAGS (UNIT_UFMASK|UNIT_DIS) /* restored flags */
/* Unit dynamic flags (dynflags) (from 4.0)
/* Unit dynamic flags (dynflags) (from 4.0)
These flags are only set dynamically */
#define UNIT_ATTMULT 000001 /* allow multiple ATT cmd */
#define UNIT_V_DF_TAPE 3 /* tape density reservation */
#define UNIT_PIPE 000002 /* file is a pipe */
#define UNIT_EXTEND 000004 /* extended SIMH tape format is enabled */
#define UNIT_V_DF_TAPE 3 /* tape density reservation (bits 3-5) */
#define UNIT_W_DF_TAPE 3
/* Register data structure */
@@ -433,7 +442,10 @@ struct sim_reg {
uint32 width; /* width */
uint32 offset; /* starting bit */
uint32 depth; /* save depth */
size_t size; /* size of location in bytes */
size_t stride; /* spacing of array elements in bytes */
uint32 flags; /* flags */
t_value maxval; /* maximum value */
uint32 qptr; /* circ q ptr */
};
@@ -443,11 +455,10 @@ struct sim_reg {
#define REG_RO 00004 /* read only */
#define REG_HIDDEN 00010 /* hidden */
#define REG_NZ 00020 /* must be non-zero */
#define REG_UNIT 00040 /* in unit struct */
#define REG_CIRC 00100 /* circular array */
#define REG_VMIO 00200 /* use VM data print/parse */
#define REG_VMAD 00400 /* use VM addr print/parse */
#define REG_FIT 01000 /* fit access to size */
#define REG_FIT 00000 /* fit access to size (obsolete) */
#define REG_HRO (REG_RO | REG_HIDDEN) /* hidden, read only */
#define REG_V_UF 16 /* device specific */
@@ -520,7 +531,7 @@ struct sim_schtab {
struct sim_brktab {
t_addr addr; /* address */
int32 typ; /* mask of types */
int32 cnt; /* proceed count */
int32 cnt; /* proceed count */
char *act; /* action string */
};
@@ -540,31 +551,117 @@ struct sim_debtab {
#define UDATA(act,fl,cap) NULL,act,NULL,NULL,NULL,0,0,(fl),0,(cap),0,0
#if defined (__STDC__) || defined (_WIN32)
#define ORDATA(nm,loc,wd) #nm, &(loc), 8, (wd), 0, 1
#define DRDATA(nm,loc,wd) #nm, &(loc), 10, (wd), 0, 1
#define HRDATA(nm,loc,wd) #nm, &(loc), 16, (wd), 0, 1
#define FLDATA(nm,loc,pos) #nm, &(loc), 2, 1, (pos), 1
#define GRDATA(nm,loc,rdx,wd,pos) #nm, &(loc), (rdx), (wd), (pos), 1
#define BRDATA(nm,loc,rdx,wd,dep) #nm, (loc), (rdx), (wd), 0, (dep)
#define VBRDATA(nm,loc,rdx,wd,dep) #nm, (loc), (rdx), (wd), 0, (dep)
#define SAVEDATA(nm,loc) \
#nm, &(loc), 8, 8, 0, sizeof(loc), REG_HRO
/* Register initialization macros.
The following macros should be used to initialize the elements of a
simulator's register array. The macros provide simplified initialization,
ensure that unspecified fields are set appropriately, and insulate the
simulator writer from changes in the underlying REG structure.
The macros take varying numbers of parameters with the following meanings:
Param Meaning
----- ------------------------------------------
nm Register symbolic name
loc Location of the associated variable
aloc Location of the associated array
floc Location of the associated structure field
rdx Display and entry radix
wd Field width in bits
off Field offset in bits from LSB
dep Number of array elements
siz Element size in bytes
str Array element spacing in bytes
The macros have the following uses:
Macro Use with
-------- ---------------------------------------------------------------
ORDATA Scalar with octal display/entry
DRDATA Scalar with decimal display/entry
HRDATA Scalar with hexadecimal display/entry
FLDATA Scalar with single bit display/entry
GRDATA Scalar with with specification of radix/width/offset parameters
BRDATA Singly-subscripted array
CRDATA Doubly-subscripted array
SRDATA Singly-subscripted array of general structure fields
URDATA Singly-subscripted array of UNIT structure fields
XRDATA Generic type with specification of all parameters
SAVEDATA Generic type used only for persistence across SAVE/RESTORE
Normally, scalar and array locations specify the variable name; the names are
converted internally to pointers as needed. However, the starting point of
a partial array may be specified by passing a pointer to the desired element.
For example:
BRDATA (SYM, array, ...)
...specifies a register starting with array element zero, while:
BRDATA (SYM, &array[3], ...)
...specifies a register starting with array element three.
For arrays of general structures, the names of the array and selected field
are given:
SRDATA (SYM, array, field, ...)
This specifies a arrayed register whose elements are array[0].field,
array[1].field, etc.
Implementation notes:
1. The "RegCheck" macro is used to ensure that each of the user macros has
the correct number of parameters. This improves maintenance reliability,
as changes to the REG structure need to be reflected only in the
"RegCheck" macro.
2. "Stringization" must occur at the first macro call level to support
register names that are themselves macros. Otherwise, macro expansion
will occur before stringization, resulting in the wrong register name.
3. Additional REG initialization values may be supplied after a macro
invocation. If present, these begin with the "flags" field.
4. The URDATA macro is obsolescent and present for backward-compatibility.
It is a special case of the generic SRDATA macro, which provides the same
functionality. Note also that URDATA requires a "flags" parameter value,
which is optional for all other macros.
5. The SAVEDATA macro is useful to indicate global variables whose values
must persist across a SAVE and RESTORE. Such data is hidden from the
register user interface.
*/
#define RegCheck(nm,loc,rdx,wd,off,dep,siz,str) \
nm, (loc), (rdx), (wd), (off), (dep), (siz), (str)
#define ORDATA(nm,loc,wd) RegCheck (#nm, &(loc), 8, (wd), 0, 1, sizeof (loc), 0)
#define DRDATA(nm,loc,wd) RegCheck (#nm, &(loc), 10, (wd), 0, 1, sizeof (loc), 0)
#define HRDATA(nm,loc,wd) RegCheck (#nm, &(loc), 16, (wd), 0, 1, sizeof (loc), 0)
#define FLDATA(nm,loc,off) RegCheck (#nm, &(loc), 2, 1, (off), 1, sizeof (loc), 0)
#define GRDATA(nm,loc,rdx,wd,off) RegCheck (#nm, &(loc), (rdx), (wd), (off), 1, sizeof (loc), 0)
#define BRDATA(nm,aloc,rdx,wd,dep) RegCheck (#nm, (aloc), (rdx), (wd), 0, (dep), sizeof *(aloc), sizeof *(aloc))
#define CRDATA(nm,aloc,rdx,wd,dep) RegCheck (#nm, (aloc), (rdx), (wd), 0, (dep), sizeof **(aloc), sizeof **(aloc))
#define SRDATA(nm,aloc,floc,rdx,wd,off,dep) \
RegCheck (#nm, &((aloc)->floc), (rdx), (wd), (off), (dep), \
sizeof ((aloc)->floc), sizeof (*(aloc)))
#define XRDATA(nm,loc,rdx,wd,off,dep,siz,str) \
RegCheck (#nm, (loc), (rdx), (wd), (off), (dep), (siz), (str))
#define URDATA(nm,loc,rdx,wd,off,dep,fl) \
#nm, &(loc), (rdx), (wd), (off), (dep), ((fl) | REG_UNIT)
#else
#define ORDATA(nm,loc,wd) "nm", &(loc), 8, (wd), 0, 1
#define DRDATA(nm,loc,wd) "nm", &(loc), 10, (wd), 0, 1
#define HRDATA(nm,loc,wd) "nm", &(loc), 16, (wd), 0, 1
#define FLDATA(nm,loc,pos) "nm", &(loc), 2, 1, (pos), 1
#define GRDATA(nm,loc,rdx,wd,pos) "nm", &(loc), (rdx), (wd), (pos), 1
#define BRDATA(nm,loc,rdx,wd,dep) "nm", (loc), (rdx), (wd), 0, (dep)
#define VBRDATA(nm,loc,rdx,wd,dep) "nm", (loc), (rdx), (wd), 0, (dep)
#define SAVEDATA(nm,loc) \
"nm", &(loc), 8, 8, 0, sizeof(loc), REG_HRO
#define URDATA(nm,loc,rdx,wd,off,dep,fl) \
"nm", &(loc), (rdx), (wd), (off), (dep), ((fl) | REG_UNIT)
#endif
RegCheck (#nm, &(loc), (rdx), (wd), (off), (dep), \
sizeof (loc), sizeof (UNIT)), (fl)
#define SAVEDATA(nm,loc) RegCheck (#nm, &(loc), 8, 8, 0, sizeof (loc), 1, 1), REG_HRO
/* Typedefs for principal structures */
@@ -587,7 +684,41 @@ typedef struct sim_debtab DEBTAB;
#include "sim_fio.h"
#include "sim_sock.h"
/* V4 compatibility definitions
/* V4 register definitions.
Implementation notes:
1. Unfortunately, the requirement that "stringization" must occur at the
first macro call level precludes defining these V4 macros in terms of
their V3 equivalents. Hence, the V3 definitions must be repeated here.
*/
#define ORDATAD(nm,loc,wd,desc) RegCheck (#nm, &(loc), 8, (wd), 0, 1, sizeof (loc), 0)
#define DRDATAD(nm,loc,wd,desc) RegCheck (#nm, &(loc), 10, (wd), 0, 1, sizeof (loc), 0)
#define HRDATAD(nm,loc,wd,desc) RegCheck (#nm, &(loc), 16, (wd), 0, 1, sizeof (loc), 0)
#define FLDATAD(nm,loc,off,desc) RegCheck (#nm, &(loc), 2, 1, (off), 1, sizeof (loc), 0)
#define GRDATAD(nm,loc,rdx,wd,off,desc) RegCheck (#nm, &(loc), (rdx), (wd), (off), 1, sizeof (loc), 0)
#define BRDATAD(nm,loc,rdx,wd,dep,desc) RegCheck (#nm, (loc), (rdx), (wd), 0, (dep), \
sizeof *(loc), sizeof *(loc))
#define URDATAD(nm,loc,rdx,wd,off,dep,fl,desc) RegCheck (#nm, &(loc), (rdx), (wd), (off), (dep), \
sizeof (loc), sizeof (UNIT)), (fl)
#define ORDATADF(nm,loc,wd,desc,flds) RegCheck (#nm, &(loc), 8, (wd), 0, 1, sizeof (loc), 0)
#define DRDATADF(nm,loc,wd,desc,flds) RegCheck (#nm, &(loc), 10, (wd), 0, 1, sizeof (loc), 0)
#define HRDATADF(nm,loc,wd,desc,flds) RegCheck (#nm, &(loc), 16, (wd), 0, 1, sizeof (loc), 0)
#define FLDATADF(nm,loc,off,desc,flds) RegCheck (#nm, &(loc), 2, 1, (off), 1, sizeof (loc), 0)
#define GRDATADF(nm,loc,rdx,wd,off,desc,flds) RegCheck (#nm, &(loc), (rdx), (wd), (off), 1, sizeof (loc), 0)
#define BRDATADF(nm,loc,rdx,wd,dep,desc,flds) RegCheck (#nm, (loc), (rdx), (wd), 0, (dep), \
sizeof *(loc), sizeof *(loc))
#define URDATADF(nm,loc,rdx,wd,off,dep,fl,desc,flds) RegCheck (#nm, &(loc), (rdx), (wd), (off), (dep), \
sizeof (loc), sizeof (UNIT)), (fl)
#ifndef INT64_C
#define INT64_C(x) (x##LL)
#endif
/* V4 compatibility definitions.
The SCP API for version 4.0 introduces a number of "pointer-to-const"
parameter qualifiers that were not present in the 3.x versions. To maintain
@@ -596,46 +727,6 @@ typedef struct sim_debtab DEBTAB;
when compiling for SIMH 3.x.
*/
#if defined (__STDC__) || defined (_WIN32)
#define ORDATAD(nm,loc,wd,desc) #nm, &(loc), 8, (wd), 0, 1
#define DRDATAD(nm,loc,wd,desc) #nm, &(loc), 10, (wd), 0, 1
#define HRDATAD(nm,loc,wd,desc) #nm, &(loc), 16, (wd), 0, 1
#define FLDATAD(nm,loc,pos,desc) #nm, &(loc), 2, 1, (pos), 1
#define GRDATAD(nm,loc,rdx,wd,pos,desc) #nm, &(loc), (rdx), (wd), (pos), 1
#define BRDATAD(nm,loc,rdx,wd,dep,desc) #nm, (loc), (rdx), (wd), 0, (dep)
#define URDATAD(nm,loc,rdx,wd,off,dep,fl,desc) \
#nm, &(loc), (rdx), (wd), (off), (dep), ((fl) | REG_UNIT)
#define ORDATADF(nm,loc,wd,desc) #nm, &(loc), 8, (wd), 0, 1
#define DRDATADF(nm,loc,wd,desc) #nm, &(loc), 10, (wd), 0, 1
#define HRDATADF(nm,loc,wd,desc) #nm, &(loc), 16, (wd), 0, 1
#define FLDATADF(nm,loc,pos,desc) #nm, &(loc), 2, 1, (pos), 1
#define GRDATADF(nm,loc,rdx,wd,pos,desc) #nm, &(loc), (rdx), (wd), (pos), 1
#define BRDATADF(nm,loc,rdx,wd,dep,desc) #nm, (loc), (rdx), (wd), 0, (dep)
#define URDATADF(nm,loc,rdx,wd,off,dep,fl,desc) \
#nm, &(loc), (rdx), (wd), (off), (dep), ((fl) | REG_UNIT)
#else
#define ORDATAD(nm,loc,wd) "nm", &(loc), 8, (wd), 0, 1
#define DRDATAD(nm,loc,wd) "nm", &(loc), 10, (wd), 0, 1
#define HRDATAD(nm,loc,wd) "nm", &(loc), 16, (wd), 0, 1
#define FLDATAD(nm,loc,pos) "nm", &(loc), 2, 1, (pos), 1
#define GRDATAD(nm,loc,rdx,wd,pos) "nm", &(loc), (rdx), (wd), (pos), 1
#define BRDATAD(nm,loc,rdx,wd,dep) "nm", (loc), (rdx), (wd), 0, (dep)
#define URDATAD(nm,loc,rdx,wd,off,dep,fl) \
"nm", &(loc), (rdx), (wd), (off), (dep), ((fl) | REG_UNIT)
#define ORDATADF(nm,loc,wd) "nm", &(loc), 8, (wd), 0, 1
#define DRDATADF(nm,loc,wd) "nm", &(loc), 10, (wd), 0, 1
#define HRDATADF(nm,loc,wd) "nm", &(loc), 16, (wd), 0, 1
#define FLDATADF(nm,loc,pos) "nm", &(loc), 2, 1, (pos), 1
#define GRDATADF(nm,loc,rdx,wd,pos) "nm", &(loc), (rdx), (wd), (pos), 1
#define BRDATADF(nm,loc,rdx,wd,dep) "nm", (loc), (rdx), (wd), 0, (dep)
#define URDATADF(nm,loc,rdx,wd,off,dep,fl) \
"nm", &(loc), (rdx), (wd), (off), (dep), ((fl) | REG_UNIT)
#endif
#ifndef INT64_C
#define INT64_C(x) (x##LL)
#endif
#ifdef PF_USER
#undef PF_USER
#endif /* PF_USER */

View File

@@ -1,6 +1,6 @@
/* sim_rev.h: simulator revisions and current rev level
Copyright (c) 1993-2020, Robert M Supnik
Copyright (c) 1993-2021, 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"),
@@ -28,19 +28,60 @@
#define _SIM_REV_H_ 0
#define SIM_MAJOR 3
#define SIM_MINOR 11
#define SIM_MINOR 12
#define SIM_PATCH 2
#define SIM_DELTA 0
/* V3.11 revision history
/* V3.12 revision history
V3.11 incorporates SCP additions and extensions by Dave Bryan to support his
HP simulators.
V3.12 incorporates a major rework of the register sizing macros and access
logic by Dave Bryan.
patch date module(s) and fix(es)
2 tbd scp.h
2 26-Mar-2022 sim_defs.h, scp.c
- deprecated UNIT_RAW, UNIT_TEXT
- dropped non-C_STD string support
sim_tape.h, sim_tape.c
- added extended tape format (Dave Bryan)
all magtape simulators
- added extra case points for new MTSE definitions
pdp11_kg.c
- fixed bug in repeated operations (Paul Koning)
pdp11_rq.c
- added additional disk types
pdp8_fpp.c
- fix fencepost error in FP multiply extended precision (Rick Murphy)
1 01-Nov-2021 scp.c
- fixed bugs in ID and search on PDP11, VAX, etc.
sim_tape.c, sim_tape.h (Dave Bryan)
- added sim_tape_erase routine
- improved tape_erase_fwd corrupt image error checking
pdp11_cpumod.c, pdp11_cpumod.h
- added MMU as settable option to 11/23, 11/40, 11/45
pdp8_cpu.c
- fixed bug in reporting device conflicts (Hans-Bernd Eggenstein)
pdp8_fpp.c
- added DEVNO reporting
pdp8_ttx.c
- added DEVNO reporting from V4
0 15-Jun-2021 scp.h
- changed sim_vm_init to build time option (Dave Bryan)
- changed register structure to separate access size from display size (Dave Bryan)
- added maximum value to register structure (Dave Bryan)
- added UNIT_PIPE dynamic flag (Dave Bryan)
scp.c
- changed sim_vm_init to build time option (Dave Bryan)
@@ -48,16 +89,31 @@ patch date module(s) and fix(es)
- flush terminal line logs at return from simulation (Dave Bryan)
- close terminal line logs at exit from simulator (Dave Bryan)
- fixed RUN problem if CPU reset clears PC (Mark Pizzolato)
- separated register access size from display size (Dave Bryan)
- added maximum value for register input (Dave Bryan)
- added support for pipes as sequential IO sources (Dave Bryan)
sim_tmxr.h, sim_tmxr.c
- added capability to flush/close log files (Dave Bryan)
i1401_defs.h, i1401_cpu.c
- added maximum value for address registers
i1620_defs.h, i1620_cpu.c
- added maximum value for address registers
i7094_mt.c
- replaced dynamic buffer allocation with static (Mark Pizzolato)
nova_cpu.c
- fixed bug in history handling of C bit (Samuel Deutsch)
pdp10_tu.c
- fixed bad macro (Mark Pizzolato)
pdp11_cpumod.h
- added MMU as settable option to 11/23, 11/40, 11/45
pdp11_cpumod.c
- fixed KDJ11E programmable rate select (Paul Koning)
@@ -67,6 +123,19 @@ patch date module(s) and fix(es)
pdp18b_dr15.c
- zero out shared section on initial allocate (Dave Bryan)
pdp18b_dt.c, pdp18b_rf.c
- fixed bug if read overwrites WC memory location
pdp8_clk.c
- added diagnostic mode for timing dependency in TSS/8
pdp8_df.c, pdp8_dt.c, pdpd8_rf.c
- fixed bug if read overwrites WC memory location
pdp8_sys.c
- fixed treatment of RUBOUT in binary loader (Mark Pizzolato)
- fixed decoding of RF/DF and LP intructions
s3_sys.c
- fixed bldaddr length (Mark Pizzolatto)
@@ -76,20 +145,30 @@ patch date module(s) and fix(es)
sds_cr.c, sds_cp.c
- New devices (Ken Rector)
sds_cpu.c, sds_mt.c, sds_rad.c
- Added C register support (Ken Rector)
sds_io.c
- TOP disconnects the channel rather than setting CHF_EOR
- Fixed overrun/underrun handling in single-word IO
sds_stddev.c
- TTO recognizes no leader flag (Ken Rector)
- Added C register support to PTR boot (Ken Rector)
sds_sys.c
- Fixed handling of SDS character value 060 (Ken Rector)
- Addec card reader and punch (Ken Rector)
- Added card reader and punch (Ken Rector)
- Added C register support to loader (Ken Rector)
vax_cpu.c
- added idle test for VMS 5.0/5.1 (Mark Pizzolato)
/* V3.11 revision history
V3.11 incorporates SCP additions and extensions by Dave Bryan to support his
HP simulators.
1 31-Mar-2020 scp.c and sim_tmxr_c
- new extensions to support HP simulators
- added SET <dev|unit> APPEND command