diff --git a/hp2100_cpu.c b/hp2100_cpu.c index 1987a14f..c49cd31a 100644 --- a/hp2100_cpu.c +++ b/hp2100_cpu.c @@ -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. + 26-Nov-00 RMS Fixed bug in dual device number routine + 21-Nov-00 RMS Fixed bug in reset routine 15-Oct-00 RMS Added dynamic device number support The register state for the HP 2100 CPU is: @@ -1325,7 +1327,7 @@ return (stop_dev << IOT_V_REASON) | dat; t_stat cpu_reset (DEVICE *dptr) { -AR = BR = 0; +saved_AR = saved_BR = 0; XR = YR = 0; E = 0; O = 0; @@ -1441,7 +1443,7 @@ return SCPE_OK; t_stat hp_setdev2 (UNIT *uptr, int32 ord) { -int32 olddev; +int32 i, olddev; t_stat r; olddev = infotab[ord].devno; @@ -1449,6 +1451,11 @@ if ((r = hp_setdev (uptr, ord)) != SCPE_OK) return r; if (infotab[ord].devno == DEVMASK) { infotab[ord].devno = olddev; return SCPE_ARG; } +for (i = 0; infotab[i].devno != 0; i++) { + if ((i != (ord + 1)) && + ((infotab[ord].devno + 1) == infotab[i].devno)) { + infotab[ord].devno = olddev; + return SCPE_ARG; } } infotab[ord + 1].devno = infotab[ord].devno + 1; return SCPE_OK; } diff --git a/hp2100_defs.h b/hp2100_defs.h index 2a5845be..676c668f 100644 --- a/hp2100_defs.h +++ b/hp2100_defs.h @@ -47,7 +47,7 @@ #define AMASK (MAXMEMSIZE - 1) /* address mask */ #define MEM_ADDR_OK(x) (((t_addr) (x)) < MEMSIZE) -/* Machine architecture */ +/* Architectural constants */ #define SIGN 0100000 /* sign */ #define DMASK 0177777 /* data mask */ @@ -86,29 +86,7 @@ struct DMA { /* DMA channel */ int32 cw3; /* word count */ }; -/* I/O macros */ - -#define INT_V(x) ((x) & 037) /* device bit pos */ -#define INT_M(x) (1u << INT_V (x)) /* device bit mask */ -#define setCMD(D) dev_cmd[(D)/32] = dev_cmd[(D)/32] | INT_M ((D)) -#define clrCMD(D) dev_cmd[(D)/32] = dev_cmd[(D)/32] & ~INT_M (D) -#define setCTL(D) dev_ctl[(D)/32] = dev_ctl[(D)/32] | INT_M ((D)) -#define clrCTL(D) dev_ctl[(D)/32] = dev_ctl[(D)/32] & ~INT_M (D) -#define setFBF(D) dev_fbf[(D)/32] = dev_fbf[(D)/32] | INT_M (D) -#define clrFBF(D) dev_fbf[(D)/32] = dev_fbf[(D)/32] & ~INT_M (D) -#define setFLG(D) dev_flg[(D)/32] = dev_flg[(D)/32] | INT_M (D); \ - setFBF(D) -#define clrFLG(D) dev_flg[(D)/32] = dev_flg[(D)/32] & ~INT_M (D); \ - clrFBF(D) -#define CMD(D) ((dev_cmd[(D)/32] >> INT_V (D)) & 1) -#define CTL(D) ((dev_ctl[(D)/32] >> INT_V (D)) & 1) -#define FLG(D) ((dev_flg[(D)/32] >> INT_V (D)) & 1) -#define FBF(D) ((dev_fbf[(D)/32] >> INT_V (D)) & 1) - -#define IOT_V_REASON 16 -#define IORETURN(f,v) ((f)? (v): SCPE_OK) /* stop on error */ - -/* I/O instruction sub-opcodes */ +/* I/O sub-opcodes */ #define ioHLT 0 /* halt */ #define ioFLG 1 /* set/clear flag */ @@ -146,6 +124,8 @@ struct DMA { /* DMA channel */ #define MTC 021 /* mag tape control */ #define DPD 022 /* disk pack data */ #define DPC 023 /* disk pack control */ +#define DPBD 024 /* second disk pack data */ +#define DPBC 025 /* second disk pack control */ /* Dynamic device information table */ @@ -169,5 +149,29 @@ struct hpdev { #define inMTC 6 #define inDPD 7 #define inDPC 8 +#define inDPBD 9 +#define inDPBC 10 #define UNIT_DEVNO (1 << UNIT_V_UF) /* dummy flag */ + +/* I/O macros */ + +#define INT_V(x) ((x) & 037) /* device bit pos */ +#define INT_M(x) (1u << INT_V (x)) /* device bit mask */ +#define setCMD(D) dev_cmd[(D)/32] = dev_cmd[(D)/32] | INT_M ((D)) +#define clrCMD(D) dev_cmd[(D)/32] = dev_cmd[(D)/32] & ~INT_M (D) +#define setCTL(D) dev_ctl[(D)/32] = dev_ctl[(D)/32] | INT_M ((D)) +#define clrCTL(D) dev_ctl[(D)/32] = dev_ctl[(D)/32] & ~INT_M (D) +#define setFBF(D) dev_fbf[(D)/32] = dev_fbf[(D)/32] | INT_M (D) +#define clrFBF(D) dev_fbf[(D)/32] = dev_fbf[(D)/32] & ~INT_M (D) +#define setFLG(D) dev_flg[(D)/32] = dev_flg[(D)/32] | INT_M (D); \ + setFBF(D) +#define clrFLG(D) dev_flg[(D)/32] = dev_flg[(D)/32] & ~INT_M (D); \ + clrFBF(D) +#define CMD(D) ((dev_cmd[(D)/32] >> INT_V (D)) & 1) +#define CTL(D) ((dev_ctl[(D)/32] >> INT_V (D)) & 1) +#define FLG(D) ((dev_flg[(D)/32] >> INT_V (D)) & 1) +#define FBF(D) ((dev_fbf[(D)/32] >> INT_V (D)) & 1) + +#define IOT_V_REASON 16 +#define IORETURN(f,v) ((f)? (v): SCPE_OK) /* stop on error */ diff --git a/hp2100_dp.c b/hp2100_dp.c index d2bc6407..7c35294a 100644 --- a/hp2100_dp.c +++ b/hp2100_dp.c @@ -24,6 +24,9 @@ in this Software without prior written authorization from Robert M Supnik. dp 12557A cartridge disk system + + 29-Nov-00 RMS Made variable names unique + 21-Nov-00 RMS Fixed flag, buffer power up state */ #include "hp2100_defs.h" @@ -108,11 +111,11 @@ int32 dpc_sta[DP_NUMDRV] = { 0 }; /* status regs */ int32 dpc_stime = 10; /* seek time */ int32 dpc_ctime = 10; /* command time */ int32 dpc_xtime = 5; /* xfer time */ -int32 rarc = 0, rarh = 0, rars = 0; /* record addr */ +int32 dpc_rarc = 0, dpc_rarh = 0, dpc_rars = 0; /* record addr */ int32 dpd_obuf = 0, dpd_ibuf = 0; /* dch buffers */ int32 dpc_obuf = 0; /* cch buffers */ -int32 dpbptr = 0; /* buffer ptr */ -unsigned int16 dbuf[DP_NUMWD]; /* sector buffer */ +int32 dp_ptr = 0; /* buffer ptr */ +unsigned int16 dp_buf[DP_NUMWD]; /* sector buffer */ t_stat dpc_svc (UNIT *uptr); t_stat dpc_reset (DEVICE *dptr); @@ -140,7 +143,7 @@ REG dpd_reg[] = { { FLDATA (CTL, infotab[inDPD].ctl, 0) }, { FLDATA (FLG, infotab[inDPD].flg, 0) }, { FLDATA (FBF, infotab[inDPD].fbf, 0) }, - { DRDATA (BPTR, dpbptr, DP_W_NUMWD) }, + { DRDATA (BPTR, dp_ptr, DP_W_NUMWD) }, { ORDATA (DEVNO, infotab[inDPD].devno, 6), REG_RO }, { NULL } }; @@ -167,9 +170,9 @@ UNIT dpc_unit[] = { REG dpc_reg[] = { { ORDATA (OBUF, dpc_obuf, 16) }, { ORDATA (BUSY, dpc_busy, 3), REG_RO }, - { ORDATA (RARC, rarc, 8) }, - { ORDATA (RARH, rarh, 2) }, - { ORDATA (RARS, rars, 4) }, + { ORDATA (RARC, dpc_rarc, 8) }, + { ORDATA (RARH, dpc_rarh, 2) }, + { ORDATA (RARS, dpc_rars, 4) }, { ORDATA (CNT, dpc_cnt, 5) }, { FLDATA (CMD, infotab[inDPC].cmd, 0) }, { FLDATA (CTL, infotab[inDPC].ctl, 0) }, @@ -344,7 +347,7 @@ switch (uptr -> FNC) { /* case function */ case FNC_SEEK: /* seek, need cyl */ if (CMD (devd)) { /* dch active? */ - rarc = DA_GETCYL (dpd_obuf); /* take cyl word */ + dpc_rarc = DA_GETCYL (dpd_obuf); /* take cyl word */ setFLG (devd); /* set dch flg */ clrCMD (devd); /* clr dch cmd */ uptr -> FNC = FNC_SEEK1; } /* advance state */ @@ -352,14 +355,14 @@ case FNC_SEEK: /* seek, need cyl */ return SCPE_OK; case FNC_SEEK1: /* seek, need hd/sec */ if (CMD (devd)) { /* dch active? */ - rarh = DA_GETHD (dpd_obuf); /* get head */ - rars = DA_GETSC (dpd_obuf); /* get sector */ + dpc_rarh = DA_GETHD (dpd_obuf); /* get head */ + dpc_rars = DA_GETSC (dpd_obuf); /* get sector */ setFLG (devd); /* set dch flg */ clrCMD (devd); /* clr dch cmd */ - st = abs (rarc - uptr -> CYL) * dpc_stime; /* calc cyl diff */ + st = abs (dpc_rarc - uptr -> CYL) * dpc_stime; /* calc diff */ if (st == 0) st = dpc_xtime; /* min time */ sim_activate (uptr, st); /* schedule op */ - uptr -> CYL = rarc; /* on cylinder */ + uptr -> CYL = dpc_rarc; /* on cylinder */ dpc_busy = 0; /* ctrl is free */ uptr -> FNC = FNC_SEEK2; } /* advance state */ else sim_activate (uptr, dpc_xtime); /* no, wait more */ @@ -376,7 +379,7 @@ case FNC_SEEK2: /* seek done */ case FNC_AR: /* arec, need cyl */ if (CMD (devd)) { /* dch active? */ - rarc = DA_GETCYL (dpd_obuf); /* take cyl word */ + dpc_rarc = DA_GETCYL (dpd_obuf); /* take cyl word */ setFLG (devd); /* set dch flg */ clrCMD (devd); /* clr dch cmd */ uptr -> FNC = FNC_AR1; } /* advance state */ @@ -384,8 +387,8 @@ case FNC_AR: /* arec, need cyl */ return SCPE_OK; case FNC_AR1: /* arec, need hd/sec */ if (CMD (devd)) { /* dch active? */ - rarh = DA_GETHD (dpd_obuf); /* get head */ - rars = DA_GETSC (dpd_obuf); /* get sector */ + dpc_rarh = DA_GETHD (dpd_obuf); /* get head */ + dpc_rars = DA_GETSC (dpd_obuf); /* get sector */ setFLG (devd); /* set dch flg */ clrCMD (devd); } /* clr dch cmd */ else { sim_activate (uptr, dpc_xtime); /* no, wait more */ @@ -404,17 +407,17 @@ case FNC_STA: /* read status */ return SCPE_OK; case FNC_REF: /* refine sector */ - if ((uptr -> CYL != rarc) || (rars >= DP_NUMSC)) + if ((uptr -> CYL != dpc_rarc) || (dpc_rars >= DP_NUMSC)) dpc_sta[drv] = dpc_sta[drv] | STA_AER; - else { for (i = 0; i < DP_NUMWD; i++) dbuf[i] = 0; - da = GETDA (rarc, rarh, rars); /* get address */ - rars = rars + 1; /* incr sector */ - if (rars >= DP_NUMSC) { /* end of trk? */ - rars = 0; /* wrap to */ - rarh = rarh ^ 1; } /* next surf */ + else { for (i = 0; i < DP_NUMWD; i++) dp_buf[i] = 0; + da = GETDA (dpc_rarc, dpc_rarh, dpc_rars); /* get addr */ + dpc_rars = dpc_rars + 1; /* incr sector */ + if (dpc_rars >= DP_NUMSC) { /* end of trk? */ + dpc_rars = 0; /* wrap to */ + dpc_rarh = dpc_rarh ^ 1; } /* next surf */ if (err = fseek (uptr -> fileref, da * sizeof (int16), SEEK_SET)) break; - fxwrite (dbuf, sizeof (int16), DP_NUMWD, uptr -> fileref); + fxwrite (dp_buf, sizeof (int16), DP_NUMWD, uptr -> fileref); err = ferror (uptr -> fileref); } break; @@ -428,40 +431,40 @@ case FNC_CHK: /* check, need cnt */ else sim_activate (uptr, dpc_xtime); /* wait more */ return SCPE_OK; case FNC_CHK1: - if ((uptr -> CYL != rarc) || (rars >= DP_NUMSC)) + if ((uptr -> CYL != dpc_rarc) || (dpc_rars >= DP_NUMSC)) dpc_sta[drv] = dpc_sta[drv] | STA_AER; - else { maxsc = ((2 - (rarh & 1)) * DP_NUMSC) - rars; + else { maxsc = ((2 - (dpc_rarh & 1)) * DP_NUMSC) - dpc_rars; if (dpc_cnt > maxsc) { /* too many sec? */ dpc_sta[drv] = dpc_sta[drv] | STA_EOC; - rarh = rarh & ~1; /* rar = 0/2, 0 */ - rars = 0; } - else { i = rars + dpc_cnt; /* final sector */ - rars = i % DP_NUMSC; /* reposition */ - rarh = rarh ^ ((i / DP_NUMSC) & 1); } } + dpc_rarh = dpc_rarh & ~1; /* rar = 0/2, 0 */ + dpc_rars = 0; } + else { i = dpc_rars + dpc_cnt; /* final sector */ + dpc_rars = i % DP_NUMSC; /* reposition */ + dpc_rarh = dpc_rarh ^ ((i / DP_NUMSC) & 1); } } break; /* done */ case FNC_RD: /* read */ if (!CMD (devd)) break; /* dch clr? done */ if (FLG (devd)) dpc_sta[drv] = dpc_sta[drv] | STA_OVR; - if (dpbptr == 0) { /* new sector? */ - if ((uptr -> CYL != rarc) || (rars >= DP_NUMSC)) { + if (dp_ptr == 0) { /* new sector? */ + if ((uptr -> CYL != dpc_rarc) || (dpc_rars >= DP_NUMSC)) { dpc_sta[drv] = dpc_sta[drv] | STA_AER; break; } if (dpc_eoc) { /* end of cyl? */ dpc_sta[drv] = dpc_sta[drv] | STA_EOC; break; } - da = GETDA (rarc, rarh, rars); /* get address */ - rars = rars + 1; /* incr address */ - if (rars >= DP_NUMSC) { /* end of trk? */ - rars = 0; /* wrap to */ - rarh = rarh ^ 1; /* next cyl */ - dpc_eoc = ((rarh & 1) == 0); } /* calc eoc */ + da = GETDA (dpc_rarc, dpc_rarh, dpc_rars); /* get addr */ + dpc_rars = dpc_rars + 1; /* incr address */ + if (dpc_rars >= DP_NUMSC) { /* end of trk? */ + dpc_rars = 0; /* wrap to */ + dpc_rarh = dpc_rarh ^ 1; /* next cyl */ + dpc_eoc = ((dpc_rarh & 1) == 0); } /* calc eoc */ if (err = fseek (uptr -> fileref, da * sizeof (int16), SEEK_SET)) break; - fxread (dbuf, sizeof (int16), DP_NUMWD, uptr -> fileref); + fxread (dp_buf, sizeof (int16), DP_NUMWD, uptr -> fileref); if (err = ferror (uptr -> fileref)) break; } - dpd_ibuf = dbuf[dpbptr++]; /* get word */ - if (dpbptr >= DP_NUMWD) dpbptr = 0; /* wrap if last */ + dpd_ibuf = dp_buf[dp_ptr++]; /* get word */ + if (dp_ptr >= DP_NUMWD) dp_ptr = 0; /* wrap if last */ setFLG (devd); /* set dch flg */ clrCMD (devd); /* clr dch cmd */ sim_activate (uptr, dpc_xtime); /* sched next word */ @@ -472,24 +475,24 @@ case FNC_WD: /* write */ dpc_sta[drv] = dpc_sta[drv] | STA_EOC; /* set status */ break; } /* done */ if (FLG (devd)) dpc_sta[drv] = dpc_sta[drv] | STA_OVR; - dbuf[dpbptr++] = dpd_obuf; /* store word */ + dp_buf[dp_ptr++] = dpd_obuf; /* store word */ if (!CMD (devd)) { /* dch clr? done */ - for ( ; dpbptr < DP_NUMWD; dpbptr++) dbuf[dpbptr] = 0; } - if (dpbptr >= DP_NUMWD) { /* buffer full? */ - if ((uptr -> CYL != rarc) || (rars >= DP_NUMSC)) { + for ( ; dp_ptr < DP_NUMWD; dp_ptr++) dp_buf[dp_ptr] = 0; } + if (dp_ptr >= DP_NUMWD) { /* buffer full? */ + if ((uptr -> CYL != dpc_rarc) || (dpc_rars >= DP_NUMSC)) { dpc_sta[drv] = dpc_sta[drv] | STA_AER; break; } - da = GETDA (rarc, rarh, rars); /* get address */ - rars = rars + 1; /* incr address */ - if (rars >= DP_NUMSC) { /* end of trk? */ - rars = 0; /* wrap to */ - rarh = rarh ^ 1; /* next cyl */ - dpc_eoc = ((rarh & 1) == 0); } /* calc eoc */ + da = GETDA (dpc_rarc, dpc_rarh, dpc_rars); /* get addr */ + dpc_rars = dpc_rars + 1; /* incr address */ + if (dpc_rars >= DP_NUMSC) { /* end of trk? */ + dpc_rars = 0; /* wrap to */ + dpc_rarh = dpc_rarh ^ 1; /* next cyl */ + dpc_eoc = ((dpc_rarh & 1) == 0); } /* calc eoc */ if (err = fseek (uptr -> fileref, da * sizeof (int16), SEEK_SET)) return TRUE; - fwrite (dbuf, sizeof (int16), DP_NUMWD, uptr -> fileref); + fwrite (dp_buf, sizeof (int16), DP_NUMWD, uptr -> fileref); if (err = ferror (uptr -> fileref)) break; - dpbptr = 0; } + dp_ptr = 0; } if (CMD (devd)) { /* dch active? */ setFLG (devd); /* set dch flg */ clrCMD (devd); /* clr dch cmd */ @@ -517,7 +520,7 @@ if (dev && ((dpc_unit[drv].flags & UNIT_ATT) == 0)) { /* attach check? */ setFLG (dev); /* set cch flag */ clrCMD (dev); } /* clr cch cmd */ else { dpc_busy = drv + 1; /* set busy */ - dpbptr = 0; /* init buf ptr */ + dp_ptr = 0; /* init buf ptr */ dpc_eoc = 0; /* clear end cyl */ dpc_unit[drv].FNC = fnc; /* save function */ sim_activate (&dpc_unit[drv], time); } /* activate unit */ @@ -533,12 +536,12 @@ int32 i; dpd_ibuf = dpd_obuf = 0; /* clear buffers */ dpc_busy = dpc_obuf = 0; dpc_eoc = 0; -dpbptr = 0; -rarc = rarh = rars = 0; /* clear rar */ +dp_ptr = 0; +dpc_rarc = dpc_rarh = dpc_rars = 0; /* clear rar */ infotab[inDPC].cmd = infotab[inDPD].cmd = 0; /* clear cmd */ infotab[inDPC].ctl = infotab[inDPD].ctl = 0; /* clear ctl */ -infotab[inDPC].fbf = infotab[inDPD].fbf = 0; /* clear flg */ -infotab[inDPC].flg = infotab[inDPD].flg = 0; /* clear fbf */ +infotab[inDPC].fbf = infotab[inDPD].fbf = 1; /* set fbf */ +infotab[inDPC].flg = infotab[inDPD].flg = 1; /* set fbf */ for (i = 0; i < DP_NUMDRV; i++) { /* loop thru drives */ sim_cancel (&dpc_unit[i]); /* cancel activity */ dpc_unit[i].FNC = 0; /* clear function */ @@ -588,7 +591,7 @@ return SCPE_OK; t_stat dpd_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw) { if (addr >= DP_NUMWD) return SCPE_NXM; -if (vptr != NULL) *vptr = dbuf[addr] & DMASK; +if (vptr != NULL) *vptr = dp_buf[addr] & DMASK; return SCPE_OK; } @@ -597,6 +600,6 @@ return SCPE_OK; t_stat dpd_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw) { if (addr >= DP_NUMWD) return SCPE_NXM; -dbuf[addr] = val & DMASK; +dp_buf[addr] = val & DMASK; return SCPE_OK; } \ No newline at end of file diff --git a/hp2100_lp.c b/hp2100_lp.c index 1cb45cc4..8e66a38b 100644 --- a/hp2100_lp.c +++ b/hp2100_lp.c @@ -25,6 +25,8 @@ lpt 12653A line printer + 21-Nov-00 RMS Fixed flag, fbf power up state + Added command flop 15-Oct-00 RMS Added variable device number support */ @@ -54,7 +56,7 @@ UNIT lpt_unit = { REG lpt_reg[] = { { ORDATA (BUF, lpt_unit.buf, 7) }, - { FLDATA (CMD, infotab[inLPT].cmd, 0), REG_HRO }, + { FLDATA (CMD, infotab[inLPT].cmd, 0) }, { FLDATA (CTL, infotab[inLPT].ctl, 0) }, { FLDATA (FLG, infotab[inLPT].flg, 0) }, { FLDATA (FBF, infotab[inLPT].fbf, 0) }, @@ -102,9 +104,12 @@ case ioMIX: /* merge */ else if (sim_is_active (&lpt_unit)) dat = dat | LPT_BUSY; break; case ioCTL: /* control clear/set */ - if (IR & AB) { clrCTL (dev); } /* CLC */ - else { setCTL (dev); /* STC */ - sim_activate (&lpt_unit, /* schedule completion */ + if (IR & AB) { /* CLC */ + clrCMD (dev); /* clear ctl, cmd */ + clrCTL (dev); } + else { setCMD (dev); /* STC */ + setCTL (dev); /* set ctl, cmd */ + sim_activate (&lpt_unit, /* schedule op */ (lpt_unit.buf < 040)? lpt_unit.wait: lpt_ctime); } break; default: @@ -118,9 +123,10 @@ t_stat lpt_svc (UNIT *uptr) int32 dev; dev = infotab[inLPT].devno; /* get dev no */ +clrCMD (dev); /* clear cmd */ if ((lpt_unit.flags & UNIT_ATT) == 0) /* attached? */ return IORETURN (lpt_stopioe, SCPE_UNATT); -setFLG (dev); /* set flag */ +setFLG (dev); /* set flag, fbf */ if (putc (lpt_unit.buf & 0177, lpt_unit.fileref) == EOF) { perror ("LPT I/O error"); clearerr (lpt_unit.fileref); @@ -134,7 +140,7 @@ return SCPE_OK; t_stat lpt_reset (DEVICE *dptr) { infotab[inLPT].cmd = infotab[inLPT].ctl = 0; /* clear cmd, ctl */ -infotab[inLPT].flg = infotab[inLPT].fbf = 0; /* clear flg, fbf*/ +infotab[inLPT].flg = infotab[inLPT].fbf = 1; /* set flg, fbf */ lpt_unit.buf = 0; sim_cancel (&lpt_unit); /* deactivate unit */ return SCPE_OK; diff --git a/hp2100_mt.c b/hp2100_mt.c index 585e2306..984638a0 100644 --- a/hp2100_mt.c +++ b/hp2100_mt.c @@ -25,6 +25,7 @@ mt 12559A nine track magnetic tape + 30-Nov-00 RMS Made variable names unique 04-Oct-98 RMS V2.4 magtape format Magnetic tapes are represented as a series of variable records @@ -40,6 +41,9 @@ If the byte count is odd, the record is padded with an extra byte of junk. File marks are represented by a byte count of 0. + + Unusually among HP peripherals, the 12559 does not have a command flop, + and its flag and flag buffer power up as clear rather than set. */ #include "hp2100_defs.h" @@ -85,8 +89,8 @@ int32 mtc_1st = 0; /* first svc flop */ int32 mtc_ctime = 1000; /* command wait */ int32 mtc_xtime = 10; /* data xfer time */ int32 mtc_stopioe = 1; /* stop on error */ -unsigned int8 dbuf[DBSIZE] = { 0 }; /* data buffer */ -t_mtrlnt mtbptr = 0, mtbmax = 0; /* buffer ptrs */ +unsigned int8 mt_buf[DBSIZE] = { 0 }; /* data buffer */ +t_mtrlnt mt_ptr = 0, mt_max = 0; /* buffer ptrs */ static const int32 mtc_cmd[] = { FNC_WC, FNC_RC, FNC_GAP, FNC_FSR, FNC_BSR, FNC_REW, FNC_RWS, FNC_WFM }; @@ -113,8 +117,8 @@ REG mtd_reg[] = { { FLDATA (CTL, infotab[inMTD].ctl, 0), REG_HRO }, { FLDATA (FLG, infotab[inMTD].flg, 0) }, { FLDATA (FBF, infotab[inMTD].fbf, 0), REG_HRO }, - { DRDATA (BPTR, mtbptr, DB_V_SIZE + 1) }, - { DRDATA (BMAX, mtbmax, DB_V_SIZE + 1) }, + { DRDATA (BPTR, mt_ptr, DB_V_SIZE + 1) }, + { DRDATA (BMAX, mt_max, DB_V_SIZE + 1) }, { ORDATA (DEVNO, infotab[inMTD].devno, 6), REG_RO }, { NULL } }; @@ -238,7 +242,7 @@ case ioOTX: /* output */ else { sim_activate (&mtc_unit, mtc_ctime); /* start tape */ mtc_fnc = dat; /* save function */ mtc_sta = STA_BUSY; /* unit busy */ - mtbptr = 0; /* init buffer ptr */ + mt_ptr = 0; /* init buffer ptr */ clrFLG (devc); /* clear flags */ clrFLG (devd); mtc_1st = 1; /* set 1st flop */ @@ -311,13 +315,13 @@ case FNC_FSR: /* space forward */ setFLG (devc); /* set cch flg */ mtc_sta = mtc_sta & ~STA_BUSY; /* update status */ fseek (mtc_unit.fileref, mtc_unit.pos, SEEK_SET); - fxread (&mtbmax, sizeof (t_mtrlnt), 1, mtc_unit.fileref); + fxread (&mt_max, sizeof (t_mtrlnt), 1, mtc_unit.fileref); if ((err = ferror (mtc_unit.fileref)) || /* error or eof? */ feof (mtc_unit.fileref)) mtc_sta = mtc_sta | STA_EOT; - else if (mtbmax == 0) { /* zero bc? */ + else if (mt_max == 0) { /* zero bc? */ mtc_sta = mtc_sta | STA_EOF; /* EOF */ mtc_unit.pos = mtc_unit.pos + sizeof (t_mtrlnt); } - else mtc_unit.pos = mtc_unit.pos + ((MTRL (mtbmax) + 1) & ~1) + + else mtc_unit.pos = mtc_unit.pos + ((MTRL (mt_max) + 1) & ~1) + (2 * sizeof (t_mtrlnt)); /* update position */ break; case FNC_BSR: /* space reverse */ @@ -327,13 +331,13 @@ case FNC_BSR: /* space reverse */ mtc_sta = mtc_sta | STA_BOT; /* update status */ break; } fseek (mtc_unit.fileref, mtc_unit.pos - sizeof (t_mtrlnt), SEEK_SET); - fxread (&mtbmax, sizeof (t_mtrlnt), 1, mtc_unit.fileref); + fxread (&mt_max, sizeof (t_mtrlnt), 1, mtc_unit.fileref); if ((err = ferror (mtc_unit.fileref)) || /* error or eof? */ feof (mtc_unit.fileref)) mtc_unit.pos = 0; - else if (mtbmax == 0) { /* zero bc? */ + else if (mt_max == 0) { /* zero bc? */ mtc_sta = mtc_sta | STA_EOF; /* EOF */ mtc_unit.pos = mtc_unit.pos - sizeof (t_mtrlnt); } - else mtc_unit.pos = mtc_unit.pos - ((MTRL (mtbmax) + 1) & ~1) - + else mtc_unit.pos = mtc_unit.pos - ((MTRL (mt_max) + 1) & ~1) - (2 * sizeof (t_mtrlnt)); /* update position */ if (mtc_unit.pos == 0) mtc_sta = mtc_sta | STA_BOT; break; @@ -344,30 +348,30 @@ case FNC_RC: /* read */ if (mtc_1st) { /* first svc? */ mtc_1st = 0; /* clr 1st flop */ fseek (mtc_unit.fileref, mtc_unit.pos, SEEK_SET); - fxread (&mtbmax, sizeof (t_mtrlnt), 1, mtc_unit.fileref); + fxread (&mt_max, sizeof (t_mtrlnt), 1, mtc_unit.fileref); if ((err = ferror (mtc_unit.fileref)) || feof (mtc_unit.fileref)) { /* error or eof? */ setFLG (devc); /* set cch flg */ mtc_sta = (mtc_sta | STA_EOT) & ~STA_BUSY; break; } - if (mtbmax == 0) { /* tape mark? */ + if (mt_max == 0) { /* tape mark? */ mtc_unit.pos = mtc_unit.pos + sizeof (t_mtrlnt); setFLG (devc); /* set cch flg */ mtc_sta = (mtc_sta | STA_EOF) & ~STA_BUSY; break; } - mtbmax = MTRL (mtbmax); /* ignore errors */ - mtc_unit.pos = mtc_unit.pos + ((mtbmax + 1) & ~1) + + mt_max = MTRL (mt_max); /* ignore errors */ + mtc_unit.pos = mtc_unit.pos + ((mt_max + 1) & ~1) + (2 * sizeof (t_mtrlnt)); /* update position */ - if ((mtbmax > DBSIZE) || (mtbmax < 12)) { + if ((mt_max > DBSIZE) || (mt_max < 12)) { setFLG (devc); /* set cch flg */ mtc_sta = (mtc_sta | STA_PAR) & ~STA_BUSY; break; } - i = fxread (dbuf, sizeof (int8), mtbmax, mtc_unit.fileref); - for ( ; i < mtbmax; i++) dbuf[i] = 0; /* fill with 0's */ + i = fxread (mt_buf, sizeof (int8), mt_max, mtc_unit.fileref); + for ( ; i < mt_max; i++) mt_buf[i] = 0; /* fill with 0's */ err = ferror (mtc_unit.fileref); } - if (mtbptr < mtbmax) { /* more chars? */ + if (mt_ptr < mt_max) { /* more chars? */ if (FLG (devd)) mtc_sta = mtc_sta | STA_TIM; - mtc_unit.buf = dbuf[mtbptr++]; /* fetch next */ + mtc_unit.buf = mt_buf[mt_ptr++]; /* fetch next */ setFLG (devd); /* set dch flg */ sim_activate (uptr, mtc_xtime); } /* re-activate */ else { setFLG (devc); /* set cch flg */ @@ -376,20 +380,20 @@ case FNC_RC: /* read */ case FNC_WC: /* write */ if (mtc_dtf) { /* xfer flop set? */ if (!mtc_1st) { /* not first? */ - if (mtbptr < DBSIZE) /* room in buffer? */ - dbuf[mtbptr++] = mtc_unit.buf; + if (mt_ptr < DBSIZE) /* room in buffer? */ + mt_buf[mt_ptr++] = mtc_unit.buf; else mtc_sta = mtc_sta | STA_PAR; } mtc_1st = 0; /* clr 1st flop */ setFLG (devd); /* set dch flag */ sim_activate (uptr, mtc_xtime); /* re-activate */ break; } - if (mtbptr) { /* write buffer */ + if (mt_ptr) { /* write buffer */ fseek (mtc_unit.fileref, mtc_unit.pos, SEEK_SET); - fxwrite (&mtbptr, sizeof (t_mtrlnt), 1, mtc_unit.fileref); - fxwrite (dbuf, sizeof (int8), mtbptr, mtc_unit.fileref); - fxwrite (&mtbptr, sizeof (t_mtrlnt), 1, mtc_unit.fileref); + fxwrite (&mt_ptr, sizeof (t_mtrlnt), 1, mtc_unit.fileref); + fxwrite (mt_buf, sizeof (int8), mt_ptr, mtc_unit.fileref); + fxwrite (&mt_ptr, sizeof (t_mtrlnt), 1, mtc_unit.fileref); err = ferror (mtc_unit.fileref); - mtc_unit.pos = mtc_unit.pos + ((mtbptr + 1) & ~1) + + mtc_unit.pos = mtc_unit.pos + ((mt_ptr + 1) & ~1) + (2 * sizeof (t_mtrlnt)); } setFLG (devc); /* set cch flg */ mtc_sta = mtc_sta & ~STA_BUSY; /* update status */ @@ -453,7 +457,7 @@ return SCPE_OK; t_stat mtd_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw) { if (addr >= DBSIZE) return SCPE_NXM; -if (vptr != NULL) *vptr = dbuf[addr] & 0377; +if (vptr != NULL) *vptr = mt_buf[addr] & 0377; return SCPE_OK; } @@ -462,6 +466,6 @@ return SCPE_OK; t_stat mtd_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw) { if (addr >= DBSIZE) return SCPE_NXM; -dbuf[addr] = val & 0377; +mt_buf[addr] = val & 0377; return SCPE_OK; } \ No newline at end of file diff --git a/hp2100_stddev.c b/hp2100_stddev.c index d78d1937..f3dedbe9 100644 --- a/hp2100_stddev.c +++ b/hp2100_stddev.c @@ -23,22 +23,29 @@ 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. - ptr paper tape reader - ptp paper tape punch - tty console - clk 12639C time base generator + ptr 12597A-002 paper tape reader + ptp 12597A-005 paper tape punch + tty 12531C buffered teleprinter interface + clk 12539A/B/C time base generator + 21-Nov-00 RMS Fixed flag, buffer power up state + Added status input for ptp, tty 15-Oct-00 RMS Added dynamic device number support + + The reader and punch, like most HP devices, have a command flop. The + teleprinter and clock do not. */ #include "hp2100_defs.h" #include #define UNIT_V_UC (UNIT_V_UF + 1) /* UC only */ #define UNIT_UC (1 << UNIT_V_UC) +#define PTP_LOW 0000040 /* low tape */ #define TM_MODE 0100000 /* mode change */ #define TM_KBD 0040000 /* enable keyboard */ #define TM_PRI 0020000 /* enable printer */ #define TM_PUN 0010000 /* enable punch */ +#define TP_BUSY 0100000 /* busy */ #define CLK_V_ERROR 4 /* clock overrun */ #define CLK_ERROR (1 << CLK_V_ERROR) @@ -81,7 +88,7 @@ UNIT ptr_unit = { REG ptr_reg[] = { { ORDATA (BUF, ptr_unit.buf, 8) }, - { FLDATA (CMD, infotab[inPTR].cmd, 0), REG_HRO }, + { FLDATA (CMD, infotab[inPTR].cmd, 0) }, { FLDATA (CTL, infotab[inPTR].ctl, 0) }, { FLDATA (FLG, infotab[inPTR].flg, 0) }, { FLDATA (FBF, infotab[inPTR].fbf, 0) }, @@ -114,7 +121,7 @@ UNIT ptp_unit = { REG ptp_reg[] = { { ORDATA (BUF, ptp_unit.buf, 8) }, - { FLDATA (CMD, infotab[inPTP].cmd, 0), REG_HRO }, + { FLDATA (CMD, infotab[inPTP].cmd, 0) }, { FLDATA (CTL, infotab[inPTP].ctl, 0) }, { FLDATA (FLG, infotab[inPTP].flg, 0) }, { FLDATA (FBF, infotab[inPTP].fbf, 0) }, @@ -243,8 +250,11 @@ case ioLIX: /* load */ dat = ptr_unit.buf; break; case ioCTL: /* control clear/set */ - if (IR & AB) { clrCTL (dev); } /* CLC */ - else { setCTL (dev); /* STC */ + if (IR & AB) { /* CLC */ + clrCMD (dev); /* clear cmd, ctl */ + clrCTL (dev); } + else { setCMD (dev); /* STC */ + setCTL (dev); /* set cmd, ctl */ sim_activate (&ptr_unit, ptr_unit.wait); } break; default: @@ -260,6 +270,7 @@ t_stat ptr_svc (UNIT *uptr) int32 dev, temp; dev = infotab[inPTR].devno; /* get device no */ +clrCMD (dev); /* clear cmd */ if ((ptr_unit.flags & UNIT_ATT) == 0) /* attached? */ return IORETURN (ptr_stopioe, SCPE_UNATT); if ((temp = getc (ptr_unit.fileref)) == EOF) { /* read byte */ @@ -280,7 +291,7 @@ return SCPE_OK; t_stat ptr_reset (DEVICE *dptr) { infotab[inPTR].cmd = infotab[inPTR].ctl = 0; /* clear cmd, ctl */ -infotab[inPTR].flg = infotab[inPTR].fbf = 0; /* clear flg, fbf */ +infotab[inPTR].flg = infotab[inPTR].fbf = 1; /* set flg, fbf */ ptr_unit.buf = 0; sim_cancel (&ptr_unit); /* deactivate unit */ return SCPE_OK; @@ -340,13 +351,19 @@ case ioSFS: /* skip flag set */ return dat; case ioLIX: /* load */ dat = 0; +case ioMIX: /* merge */ + if ((ptp_unit.flags & UNIT_ATT) == 0) + dat = dat | PTP_LOW; /* out of tape? */ break; case ioOTX: /* output */ ptp_unit.buf = dat; break; case ioCTL: /* control clear/set */ - if (IR & AB) { clrCTL (dev); } /* CLC */ - else { setCTL (dev); /* STC */ + if (IR & AB) { /* CLC */ + clrCMD (dev); /* clear cmd, ctl */ + clrCTL (dev); } + else { setCMD (dev); /* STC */ + setCTL (dev); /* set cmd, ctl */ sim_activate (&ptp_unit, ptp_unit.wait); } break; default: @@ -362,7 +379,8 @@ t_stat ptp_svc (UNIT *uptr) int32 dev; dev = infotab[inPTP].devno; /* get device no */ -setFLG (dev); /* set device flag */ +clrCMD (dev); /* clear cmd */ +setFLG (dev); /* set flag */ if ((ptp_unit.flags & UNIT_ATT) == 0) /* attached? */ return IORETURN (ptp_stopioe, SCPE_UNATT); if (putc (ptp_unit.buf, ptp_unit.fileref) == EOF) { /* output byte */ @@ -378,7 +396,7 @@ return SCPE_OK; t_stat ptp_reset (DEVICE *dptr) { infotab[inPTP].cmd = infotab[inPTP].ctl = 0; /* clear cmd, ctl */ -infotab[inPTP].flg = infotab[inPTP].fbf = 0; /* clear flg, fbf */ +infotab[inPTP].flg = infotab[inPTP].fbf = 1; /* set flg, fbf */ ptp_unit.buf = 0; sim_cancel (&ptp_unit); /* deactivate unit */ return SCPE_OK; @@ -401,11 +419,12 @@ case ioSFC: /* skip flag clear */ case ioSFS: /* skip flag set */ if (FLG (dev) != 0) PC = (PC + 1) & AMASK; return dat; +case ioLIX: /* load */ + dat = 0; case ioMIX: /* merge */ dat = dat | tty_buf; - break; -case ioLIX: /* load */ - dat = tty_buf; + if (!(tty_mode & TM_KBD) && sim_is_active (&tty_unit[TTO])) + dat = dat | TP_BUSY; break; case ioOTX: /* output */ if (dat & TM_MODE) tty_mode = dat; @@ -425,33 +444,10 @@ return dat; /* Unit service routines */ -t_stat tti_svc (UNIT *uptr) +t_stat tto_out (int32 ch) { -int32 temp, dev; +t_stat ret = SCPE_OK; -dev = infotab[inTTY].devno; /* get device no */ -sim_activate (&tty_unit[TTI], tty_unit[TTI].wait); /* continue poll */ -if ((temp = sim_poll_kbd ()) < SCPE_KFLAG) return temp; /* no char or error? */ -temp = temp & 0177; -if ((tty_unit[TTO].flags & UNIT_UC) && islower (temp)) /* force upper case? */ - temp = toupper (temp); -if (tty_mode & TM_KBD) { /* keyboard enabled? */ - tty_buf = temp; /* put char in buf */ - tty_unit[TTI].pos = tty_unit[TTI].pos + 1; - setFLG (dev); /* set flag */ - if (tty_mode & TM_PRI) sim_putchar (temp); } /* echo? */ -return SCPE_OK; -} - -t_stat tto_svc (UNIT *uptr) -{ -int32 ch, ret, dev; - -dev = infotab[inTTY].devno; /* get device no */ -ret = SCPE_OK; /* assume ok */ -setFLG (dev); /* set done flag */ -ch = tty_buf; -tty_buf = 0377; /* defang buf */ if (tty_mode & TM_PRI) { /* printing? */ ret = sim_putchar (ch & 0177); /* output char */ tty_unit[TTO].pos = tty_unit[TTO].pos + 1; } @@ -466,12 +462,41 @@ if (tty_mode & TM_PUN) { /* punching? */ return ret; } +t_stat tti_svc (UNIT *uptr) +{ +int32 temp, dev; + +dev = infotab[inTTY].devno; /* get device no */ +sim_activate (&tty_unit[TTI], tty_unit[TTI].wait); /* continue poll */ +if ((temp = sim_poll_kbd ()) < SCPE_KFLAG) return temp; /* no char or error? */ +temp = temp & 0177; +if ((tty_unit[TTI].flags & UNIT_UC) && islower (temp)) /* force upper case? */ + temp = toupper (temp); +if (tty_mode & TM_KBD) { /* keyboard enabled? */ + tty_buf = temp; /* put char in buf */ + tty_unit[TTI].pos = tty_unit[TTI].pos + 1; + setFLG (dev); /* set flag */ + return tto_out (temp); } /* echo or punch? */ +return SCPE_OK; +} + +t_stat tto_svc (UNIT *uptr) +{ +int32 ch, dev; + +dev = infotab[inTTY].devno; /* get device no */ +setFLG (dev); /* set done flag */ +ch = tty_buf; +tty_buf = 0377; /* defang buf */ +return tto_out (ch); /* print and/or punch */ +} + /* Reset routine */ t_stat tty_reset (DEVICE *dptr) { infotab[inTTY].cmd = infotab[inTTY].ctl = 0; /* clear cmd, ctl */ -infotab[inTTY].flg = infotab[inTTY].fbf = 0; /* clear flg, fbf */ +infotab[inTTY].flg = infotab[inTTY].fbf = 1; /* set flg, fbf */ tty_mode = 0; tty_buf = 0; sim_activate (&tty_unit[TTI], tty_unit[TTI].wait); /* activate poll */ @@ -498,6 +523,7 @@ case ioSFS: /* skip flag set */ return dat; case ioMIX: /* merge */ dat = dat | clk_error; + break; case ioLIX: /* load */ dat = clk_error; break; @@ -535,7 +561,7 @@ return SCPE_OK; t_stat clk_reset (DEVICE *dptr) { infotab[inCLK].cmd = infotab[inCLK].ctl = 0; /* clear cmd, ctl */ -infotab[inCLK].flg = infotab[inCLK].fbf = 0; /* clear flg, fbf */ +infotab[inCLK].flg = infotab[inCLK].fbf = 1; /* set flg, fbf */ clk_error = 0; /* clear error */ clk_select = 0; /* clear select */ sim_cancel (&clk_unit); /* deactivate unit */ diff --git a/i1401_cd.c b/i1401_cd.c index 8bed81b2..06c2edf8 100644 --- a/i1401_cd.c +++ b/i1401_cd.c @@ -1,6 +1,6 @@ /* i1401_cd.c: IBM 1402 card reader/punch - Copyright (c) 1993-1999, Robert M. Supnik + Copyright (c) 1993-2000, 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"), diff --git a/i1401_cpu.c b/i1401_cpu.c index 9b49fc99..b1b5e218 100644 --- a/i1401_cpu.c +++ b/i1401_cpu.c @@ -1,6 +1,6 @@ /* i1401_cpu.c: IBM 1401 CPU simulator - Copyright (c) 1993-1999, Robert M. Supnik + Copyright (c) 1993-2000, 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,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. + 07-Dec-00 RMS Fixed bugs found by Charles Owen + -- 4,7 char NOPs are legal + -- 1 char B is chained BCE + -- MCE moves whole char after first 14-Apr-99 RMS Changed t_addr to unsigned The register state for the IBM 1401 is: @@ -256,7 +260,7 @@ const int32 op_table[64] = { L2 | L5, /* select stacker */ L1 | L4 | L7 | L8 | BREQ | MLS | IO, /* load */ L1 | L4 | L7 | L8 | BREQ | MLS | IO, /* move */ - HNOP | L1, /* nop */ + HNOP | L1 | L4 | L7, /* nop */ 0, /* illegal */ L1 | L4 | L7 | AREQ | BREQ | MR, /* move to record */ L1 | L4 | AREQ | MLS, /* 50: store A addr */ @@ -599,16 +603,16 @@ case OP_C: /* compare */ /* Branch instructions A check B check - B 8 char: branch if B char equals d if branch here - B 5 char: branch if indicator[d] is set if branch + B 1/8 char: branch if B char equals d if branch here B 4 char: unconditional branch if branch + B 5 char: branch if indicator[d] is set if branch BWZ: branch if (d<0>: B char WM) if branch here (d<1>: B char zone = d zone) BBE: branch if B char & d non-zero if branch here */ case OP_B: /* branch */ - if (ilnt <= 4) { BRANCH; } /* uncond branch? */ + if (ilnt == 4) { BRANCH; } /* uncond branch? */ else if (ilnt == 5) { /* branch on ind? */ if (ind[D]) { BRANCH; } /* test indicator */ if (ind_table[D]) ind[D] = 0; } /* reset if needed */ @@ -783,6 +787,17 @@ case OP_RF: case OP_PF: /* read, punch feed */ qdollar EPE only; $ seen in body qaster EPE only; * seen in body qdecimal EPE only; . seen on first rescan + + MCE operates in one to three scans, the first of which has three phases + + 1 right to left qbody = 0, qawm = 0 => right status + qbody = 1, qawm = 0 => body + qbody = 0, qawm = 1 => left status + 2 left to right + 3 right to left, extended print end only + + The first A field character is masked to its digit part, all others + are copied intact */ case OP_MCE: /* edit */ @@ -799,7 +814,17 @@ case OP_MCE: /* edit */ qawm = qzero = qbody = 0; /* clear other flags */ qdollar = qaster = qdecimal = 0; /* clear EPE flags */ -/* Edit pass 1 - from right to left, under B field control */ +/* Edit pass 1 - from right to left, under B field control + + * in status or !epe, skip B; else, set qaster, repl with A + $ in status or !epe, skip B; else, set qdollar, repl with A + 0 in right status or body, if !qzero, set A WM; set qzero, repl with A + else, if !qzero, skip B; else, if (!B WM) set B WM + blank in right status or body, repl with A; else, skip B + C,R,- in status, blank B; else, skip B + , in status, blank B, else, skip B + & blank B +*/ do { b = M[BS]; /* get B char */ M[BS] = M[BS] & ~WM; /* clr WM */ @@ -818,7 +843,7 @@ case OP_MCE: /* edit */ qzero = 1; /* flag supress */ break; } if (!qzero) t = t | WM; /* first? set WM */ - qzero = 1; /* flag suppress */ + qzero = 1; /* flag supress */ /* fall through */ case BCD_BLANK: /* blank */ if (qawm) break; /* any A left? */ @@ -829,7 +854,7 @@ case OP_MCE: /* edit */ qawm = 1; } else { qbody = 1; /* in body */ a = M[AS]; MM (AS); /* next A */ - t = a & DIGIT; } + t = a & CHAR; } break; case BCD_C: case BCD_R: case BCD_MINUS: /* C, R, - */ if (!qsign && !qbody) M[BS] = BCD_BLANK; @@ -847,7 +872,7 @@ case OP_MCE: /* edit */ if (qdollar) reason = STOP_MCE3; /* error if $ */ break; } -/* Edit pass 2 - from left to right, suppressing zeroes */ +/* Edit pass 2 - from left to right, supressing zeroes */ do { b = M[++BS]; /* get B char */ switch (b & CHAR) { /* case on B char */ diff --git a/i1401_defs.h b/i1401_defs.h index 15be2922..a2a07baf 100644 --- a/i1401_defs.h +++ b/i1401_defs.h @@ -1,6 +1,6 @@ /* i1401_defs.h: IBM 1401 simulator definitions - Copyright (c) 1993-1999, Robert M. Supnik + Copyright (c) 1993-2000, 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"), @@ -27,7 +27,8 @@ This simulator is based on the 1401 simulator written by Len Fehskens with assistance from Sarah Lee Harris and Bob Supnik. This one's for - you, Len. + you, Len. I am grateful to Paul Pierce and Charles Owen for their help + in answering questions, gathering source material, and debugging. */ #include "sim_defs.h" diff --git a/i1401_iq.c b/i1401_iq.c index a55c4ebb..c6370afb 100644 --- a/i1401_iq.c +++ b/i1401_iq.c @@ -1,6 +1,6 @@ /* i1401_iq.c: IBM 1407 inquiry terminal - Copyright (c) 1993-1999, Robert M. Supnik + Copyright (c) 1993-2000, 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"), diff --git a/i1401_lp.c b/i1401_lp.c index 3ad38b8e..3fff36c6 100644 --- a/i1401_lp.c +++ b/i1401_lp.c @@ -1,6 +1,6 @@ /* i1401_lp.c: IBM 1403 line printer simulator - Copyright (c) 1993-1999, Robert M. Supnik + Copyright (c) 1993-2000, 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"), diff --git a/i1401_mt.c b/i1401_mt.c index 0e78b759..c06db181 100644 --- a/i1401_mt.c +++ b/i1401_mt.c @@ -1,6 +1,6 @@ /* IBM 1401 magnetic tape simulator - Copyright (c) 1993-1999, Robert M. Supnik + Copyright (c) 1993-2000, 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,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. + 07-Dec-00 RMS Widened display width from 6 to 8 bits to see record lnt + CEO Added tape bootstrap 14-Apr-99 RMS Changed t_addr to unsigned 04-Oct-98 RMS V2.4 magtape format @@ -54,6 +56,7 @@ extern int32 BS, iochk; extern UNIT cpu_unit; unsigned int8 dbuf[MAXMEMSIZE * 2]; /* tape buffer */ t_stat mt_reset (DEVICE *dptr); +t_stat mt_boot (int32 unitno); UNIT *get_unit (int32 unit); extern size_t fxread (void *bptr, size_t size, size_t count, FILE *fptr); extern size_t fxwrite (void *bptr, size_t size, size_t count, FILE *fptr); @@ -106,9 +109,9 @@ MTAB mt_mod[] = { DEVICE mt_dev = { "MT", mt_unit, mt_reg, mt_mod, - MT_NUMDR, 10, 31, 1, 8, 6, + MT_NUMDR, 10, 31, 1, 8, 8, NULL, NULL, &mt_reset, - NULL, NULL, NULL }; + &mt_boot, NULL, NULL }; /* Function routine @@ -266,3 +269,25 @@ t_stat mt_reset (DEVICE *dptr) ind[IN_END] = ind[IN_PAR] = ind[IN_TAP] = 0; /* clear indicators */ return SCPE_OK; } + +/* Bootstrap routine */ + +#define BOOT_START 3980 +#define BOOT_LEN (sizeof (boot_rom) / sizeof (unsigned char)) + +static const unsigned char boot_rom[] = { + OP_LCA + WM, BCD_PERCNT, BCD_U, BCD_ONE, + BCD_ZERO, BCD_ZERO, BCD_ONE, BCD_R, /* LDA %U1 001 R */ + OP_B + WM, BCD_ZERO, BCD_ZERO, BCD_ONE, /* B 001 */ + OP_H + WM }; /* HALT */ + +t_stat mt_boot (int32 unitno) +{ +int32 i; +extern int32 saved_IS; + +for (i = 0; i < BOOT_LEN; i++) M[BOOT_START + i] = boot_rom[i]; +M[BOOT_START + 3] = unitno & 07; +saved_IS = BOOT_START; +return SCPE_OK; +} diff --git a/id4_defs.h b/id4_defs.h index c7b85475..132e24aa 100644 --- a/id4_defs.h +++ b/id4_defs.h @@ -42,6 +42,13 @@ #include "sim_defs.h" /* simulator defns */ +/* Simulator stop codes */ + +#define STOP_RSRV 1 /* must be 1 */ +#define STOP_HALT 2 /* HALT */ +#define STOP_IBKPT 3 /* breakpoint */ +#define STOP_WAIT 4 /* wait */ + /* Memory */ #define MAXMEMSIZE 65536 /* max memory size */ @@ -86,13 +93,6 @@ #define IDOPSW 0x48 /* int div fault old PSW */ #define IDNPSW 0x4C /* int div fault new PSW */ -/* Simulator stop codes */ - -#define STOP_RSRV 1 /* must be 1 */ -#define STOP_HALT 2 /* HALT */ -#define STOP_IBKPT 3 /* breakpoint */ -#define STOP_WAIT 4 /* wait */ - /* I/O operations */ #define IO_ADR 0x0 /* address select */ @@ -123,7 +123,7 @@ #define STA_EOM 0x2 /* end of medium */ #define STA_DU 0x1 /* device unavailable */ -/* Range of implemented device numbers */ +/* Device numbers */ #define DEV_LOW 0x01 /* lowest intr dev */ #define DEV_MAX 0xFF /* highest intr dev */ @@ -133,6 +133,9 @@ #define TT 0x02 /* teletype */ #define PT 0x03 /* paper tape */ #define CD 0x04 /* card reader */ + +/* I/O macros */ + #define INT_V(d) (1u << ((d) & 0x1F)) #define SET_INT(d) int_req[(d)/32] = int_req[(d)/32] | INT_V (d) #define CLR_INT(d) int_req[(d)/32] = int_req[(d)/32] & ~INT_V (d) diff --git a/nova_clk.c b/nova_clk.c index e779f00d..ad237004 100644 --- a/nova_clk.c +++ b/nova_clk.c @@ -1,6 +1,6 @@ /* nova_clk.c: NOVA real-time clock simulator - Copyright (c) 1993-1999, Robert M. Supnik + Copyright (c) 1993-2000, 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,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. - 24-Sep-97 RMS Fixed bug in unit service (found by Dutch Owen) + 24-Sep-97 RMS Fixed bug in unit service (found by Charles Owen) clk real-time clock */ @@ -35,8 +35,6 @@ int32 clk_sel = 0; /* selected freq */ int32 clk_alt_time[4] = { 16000, 100000, 10000, 1000 }; /* freq table */ t_stat clk_svc (UNIT *uptr); t_stat clk_reset (DEVICE *dptr); -extern t_stat sim_activate (UNIT *uptr, int32 delay); -extern t_stat sim_cancel (UNIT *uptr); /* CLK data structures diff --git a/nova_cpu.c b/nova_cpu.c index faa349f9..535edd8c 100644 --- a/nova_cpu.c +++ b/nova_cpu.c @@ -23,6 +23,15 @@ 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. + 22-Dec-00 RMS Added Bruce Ray's second terminal + 15-Dec-00 RMS Added Charles Owen's CPU bootstrap + 08-Dec-00 RMS Changes from Bruce Ray + -- fixed trap test to include Nova 3 + -- fixed DIV and DIVS divide by 0 + -- fixed RETN to set SP from FP + -- fixed IORST to preserve carry + -- added "secret" Nova 4 PSHN/SAVEN instructions + -- added plotter support 15-Oct-00 RMS Fixed bug in MDV test, added stack, byte, trap instructions 14-Apr-98 RMS Changed t_addr to unsigned 15-Sep-97 RMS Added read and write breakpoints @@ -57,7 +66,7 @@ 010 AC2 relative direct MA = AC2 + sext (IR<8:15>) 011 AC3 relative direct MA = AC3 + sext (IR<8:15>) 100 page zero indirect MA = M[zext (IR<8:15>)] - 101 PC relative dinirect MA = M[PC + sext (IR<8:15>)] + 101 PC relative indirect MA = M[PC + sext (IR<8:15>)] 110 AC2 relative indirect MA = M[AC2 + sext (IR<8:15>)] 111 AC3 relative indirect MA = M[AC3 + sext (IR<8:15>)] @@ -111,6 +120,37 @@ The operate instruction can be microprogrammed to perform operations on the source and destination AC's and the Carry flag. + + Some notes from Bruce Ray: + + 1. DG uses the value of the autoindex location -before- the + modification to determine if additional indirect address + levels are to be performed. Most DG emulators conform to + this standard, but some vendor machines (i.e. Point 4 Mark 8) + do not. + + 2. Infinite indirect references may occur on unmapped systems + and can "hang" the hardware. Some DG diagnostics perform + 10,000s of references during a single instruction. + + 3. Nova 3 adds the following instructions to the standard Nova + instruction set: + + trap instructions + stack push/pop instructions + save/return instructions + stack register manipulation instructions + unsigned MUL/DIV + + 4. Nova 4 adds the following instructions to the Nova 3 instruction + set: + + signed MUL/DIV + load/store byte + secret (undocumented) stack instructions [PSHN, SAVN] + + 5. Nova, Nova 3 and Nova 4 unsigned mul/div instructions are the + same instruction code values on all machines. */ /* This routine is the instruction decode routine for the NOVA. @@ -203,11 +243,15 @@ t_stat cpu_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw); t_stat cpu_reset (DEVICE *dptr); t_stat cpu_svc (UNIT *uptr); t_stat cpu_set_size (UNIT *uptr, int32 value); +t_stat cpu_boot (int32 unitno); 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); @@ -224,7 +268,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 }, @@ -238,7 +282,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 }, @@ -420,8 +464,8 @@ if (IR & I_OPR) { /* operate? */ break; } /* end switch shift */ switch (I_GETSKP (IR)) { /* decode skip */ case 0: /* nop */ - if ((IR & I_NLD) && (cpu_unit.flags & UNIT_BYT)) { - register int32 indf, MA; /* Nova 4 trap */ + if ((IR & I_NLD) && (cpu_unit.flags & UNIT_STK)) { + register int32 indf, MA; /* Nova 3 or 4 trap */ old_PC = M[TRP_SAV] = (PC - 1) & AMASK; MA = TRP_JMP; /* jmp @47 */ for (i = 0, indf = 1; indf && (i < ind_max); i++) { @@ -576,6 +620,7 @@ else { /* IOT */ if (cpu_unit.flags & UNIT_BYT) AC[dstAC] = (M[AC[pulse] >> 1] >> ((AC[pulse] & 1)? 0: 8)) & 0377; + else AC[dstAC] = 0; break; case ioDOA: /* stack ptr */ if (cpu_unit.flags & UNIT_STK) { @@ -584,13 +629,20 @@ else { /* IOT */ break; case ioDIB: /* push, pop */ if (cpu_unit.flags & UNIT_STK) { - if (pulse == iopN) { + if (pulse == iopN) { /* push */ SP = INCA (SP); if (MEM_ADDR_OK (SP)) M[SP] = AC[dstAC]; STK_CHECK (SP, 1); } - if (pulse == iopC) { + if (pulse == iopC) { /* pop */ AC[dstAC] = M[SP]; - SP = DECA (SP); } } + SP = DECA (SP); } + if ((pulse == iopP) && /* Nova 4 pshn */ + (cpu_unit.flags & UNIT_BYT)) { + SP = INCA (SP); + if (MEM_ADDR_OK (SP)) M[SP] = AC[dstAC]; + if (SP > M[042]) int_req = int_req | INT_STK ; + } + } break; case ioDOB: /* store byte */ if (cpu_unit.flags & UNIT_BYT) { @@ -603,7 +655,7 @@ else { /* IOT */ break; case ioDIC: /* save, return */ if (cpu_unit.flags & UNIT_STK) { - if (pulse == iopN) { + if (pulse == iopN) { /* save */ SP = INCA (SP); if (MEM_ADDR_OK (SP)) M[SP] = AC[0]; SP = INCA (SP); @@ -615,10 +667,11 @@ else { /* IOT */ SP = INCA (SP); if (MEM_ADDR_OK (SP)) M[SP] = (C >> 1) | (AC[3] & AMASK); - AC[3] = FP = SP; + AC[3] = FP = SP & AMASK; STK_CHECK (SP, 5); } - if (pulse == iopC) { + if (pulse == iopC) { /* retn */ old_PC = PC; + SP = FP & AMASK; C = (M[SP] << 1) & CBIT; PC = M[SP] & AMASK; SP = DECA (SP); @@ -630,7 +683,27 @@ else { /* IOT */ SP = DECA (SP); AC[0] = M[SP]; SP = DECA (SP); - FP = AC[3] & AMASK; } } + FP = AC[3] & AMASK; } + if ((pulse == iopP) && /* Nova 4 saven */ + (cpu_unit.flags & UNIT_BYT)) { + int32 frameSz = M[PC] ; + PC = INCA (PC) ; + SP = INCA (SP); + if (MEM_ADDR_OK (SP)) M[SP] = AC[0]; + SP = INCA (SP); + if (MEM_ADDR_OK (SP)) M[SP] = AC[1]; + SP = INCA (SP); + if (MEM_ADDR_OK (SP)) M[SP] = AC[2]; + SP = INCA (SP); + if (MEM_ADDR_OK (SP)) M[SP] = FP; + SP = INCA (SP); + if (MEM_ADDR_OK (SP)) M[SP] = (C >> 1) | + (AC[3] & AMASK); + AC[3] = FP = SP & AMASK ; + SP = (SP + frameSz) & AMASK ; + if (SP > M[042]) int_req = int_req | INT_STK; + } + } break; case ioDOC: if ((dstAC == 2) && (cpu_unit.flags & UNIT_MDV)) { @@ -643,7 +716,8 @@ else { /* IOT */ AC[0] = (mddata >> 16) & DMASK; AC[1] = mddata & DMASK; } if (pulse == iopS) { /* div */ - if (uAC0 >= uAC2) C = CBIT; + if ((uAC0 >= uAC2) || (uAC2 == 0)) + C = CBIT; else { C = 0; mddata = (uAC0 << 16) | uAC1; AC[1] = mddata / uAC2; @@ -656,7 +730,7 @@ else { /* IOT */ AC[0] = (mddata >> 16) & DMASK; AC[1] = mddata & DMASK; } if (pulse == iopN) { /* divs */ - if (AC[0] == 0) C = CBIT; + if (AC[2] == 0) C = CBIT; else { mddata = (SEXT (AC[0]) << 16) | AC[1]; AC[1] = mddata / SEXT (AC[2]); AC[0] = mddata % SEXT (AC[2]); @@ -738,7 +812,6 @@ return; t_stat cpu_reset (DEVICE *dptr) { -C = 0; int_req = int_req & ~(INT_ION | INT_STK); pimask = 0; dev_disable = 0; @@ -787,3 +860,56 @@ MEMSIZE = value; for (i = MEMSIZE; i < MAXMEMSIZE; i++) M[i] = 0; return SCPE_OK; } + +/* Bootstrap routine for CPU */ + +#define BOOT_START 00000 +#define BOOT_LEN (sizeof (boot_rom) / sizeof (int)) + +static const int32 boot_rom[] = { + 0062677, /* IORST ;reset all I/O */ + 0060477, /* READS 0 ;read SR into AC0 */ + 0024026, /* LDA 1,C77 ;get dev mask */ + 0107400, /* AND 0,1 ;isolate dev code */ + 0124000, /* COM 1,1 ;- device code - 1 */ + 0010014, /* LOOP: ISZ OP1 ;device code to all */ + 0010030, /* ISZ OP2 ;I/O instructions */ + 0010032, /* ISZ OP3 */ + 0125404, /* INC 1,1,SZR ;done? */ + 0000005, /* JMP LOOP ;no, increment again */ + 0030016, /* LDA 2,C377 ;place JMP 377 into */ + 0050377, /* STA 2,377 ;location 377 */ + 0060077, /* OP1: 060077 ;start device (NIOS 0) */ + 00101102, /* MOVL 0,0,SZC ;test switch 0, low speed? */ + 0000377, /* C377: JMP 377 ;no - jmp 377 & wait */ + 0004030, /* LOOP2: JSR GET+1 ;get a frame */ + 0101065, /* MOVC 0,0,SNR ;is it non-zero? */ + 0000017, /* JMP LOOP2 ;no, ignore */ + 0004027, /* LOOP4: JSR GET ;yes, get full word */ + 0046026, /* STA 1,@C77 ;store starting at 100 */ + /* ;2's complement of word ct */ + 0010100, /* ISZ 100 ;done? */ + 0000022, /* JMP LOOP4 ;no, get another */ + 0000077, /* C77: JMP 77 ;yes location ctr and */ + /* ;jmp to last word */ + 0126420, /* GET: SUBZ 1,1 ; clr AC1, set carry */ + /* OP2: */ + 0063577, /* LOOP3: 063577 ;done? (SKPDN 0) - 1 */ + 0000030, /* JMP LOOP3 ;no -- wait */ + 0060477, /* OP3: 060477 ;y -- read in ac0 (DIAS 0,0) */ + 0107363, /* ADDCS 0,1,SNC ;add 2 frames swapped - got 2nd? */ + 0000030, /* JMP LOOP3 ;no go back after it */ + 0125300, /* MOVS 1,1 ;yes swap them */ + 0001400, /* JMP 0,3 ;rtn with full word */ + 0000000 /* 0 ;padding */ +}; + +t_stat cpu_boot (int32 unitno) +{ +int32 i; +extern int32 saved_PC; + +for (i = 0; i < BOOT_LEN; i++) M[BOOT_START + i] = boot_rom[i]; +saved_PC = BOOT_START; +return SCPE_OK; +} diff --git a/nova_defs.h b/nova_defs.h index 187c5d4d..cd377217 100644 --- a/nova_defs.h +++ b/nova_defs.h @@ -1,4 +1,4 @@ -/* nova_defs.h: NOVA simulator definitions +/* nova_defs.h: NOVA/Eclipse simulator definitions Copyright (c) 1993-2000, Robert M. Supnik @@ -23,22 +23,40 @@ 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. + 22-Dec-00 RMS Added Bruce Ray's second terminal support + 10-Dec-00 RMS Added Charles Owen's Eclipse support + 08-Dec-00 RMS Added Bruce Ray's plotter support 15-Oct-00 RMS Added stack, byte, trap instructions 14-Apr-99 RMS Changed t_addr to unsigned 16-Mar-95 RMS Added dynamic memory size 06-Dec-95 RMS Added magnetic tape - The author gratefully acknowledges the help of Tom West, Diana - Engelbart, and Carl Friend in resolving questions about the NOVA. + The author gratefully acknowledges the help of Tom West, Diana Englebart, + Carl Friend, Bruce Ray, and Charles Owen in resolving questions about + the NOVA. */ #include "sim_defs.h" /* simulator defns */ +/* Simulator stop codes */ + +#define STOP_RSRV 1 /* must be 1 */ +#define STOP_HALT 2 /* HALT */ +#define STOP_IBKPT 3 /* breakpoint */ +#define STOP_IND 4 /* indirect loop */ +#define STOP_IND_INT 5 /* ind loop, intr */ +#define STOP_IND_TRP 6 /* ind loop, trap */ + /* Memory */ +#if defined (ECLIPSE) +#define MAXMEMSIZE 1048576 /* max memory size */ +#else #define MAXMEMSIZE 32768 /* max memory size */ +#endif +#define AMASK 077777 /* logical addr mask */ +#define PAMASK (MAXMEMSIZE - 1) /* physical addr mask */ #define MEMSIZE (cpu_unit.capac) /* actual memory size */ -#define AMASK (MAXMEMSIZE - 1) /* address mask */ #define A_V_IND 15 /* ind: indirect */ #define A_IND (1 << A_V_IND) #define MEM_ADDR_OK(x) (((t_addr) (x)) < MEMSIZE) @@ -50,6 +68,18 @@ #define CBIT (DMASK + 1) /* carry bit */ #define CMASK (CBIT | DMASK) /* carry + data */ +/* Reserved memory locations */ + +#define INT_SAV 0 /* intr saved PC */ +#define INT_JMP 1 /* intr jmp @ */ +#define STK_JMP 3 /* stack jmp @ */ +#define TRP_SAV 046 /* trap saved PC */ +#define TRP_JMP 047 /* trap jmp @ */ +#define AUTO_INC 020 /* start autoinc */ +#define AUTO_DEC 030 /* start autodec */ + +/* Instruction format */ + #define I_OPR 0100000 /* operate */ #define I_M_SRC 03 /* OPR: src AC */ #define I_V_SRC 13 @@ -96,30 +126,14 @@ #define I_V_DEV 0 #define I_GETDEV(x) (((x) >> I_V_DEV) & I_M_DEV) -/* Special memory locations */ - -#define INT_SAV 0 /* intr saved PC */ -#define INT_JMP 1 /* intr jmp @ */ -#define STK_JMP 3 /* stack jmp @ */ -#define TRP_SAV 046 /* trap saved PC */ -#define TRP_JMP 047 /* trap jmp @ */ -#define AUTO_INC 020 /* start autoinc */ -#define AUTO_DEC 030 /* start autodec */ - -/* Instruction format */ - -/* Simulator stop codes */ - -#define STOP_RSRV 1 /* must be 1 */ -#define STOP_HALT 2 /* HALT */ -#define STOP_IBKPT 3 /* breakpoint */ -#define STOP_IND 4 /* indirect loop */ -#define STOP_IND_INT 5 /* ind loop, intr */ -#define STOP_IND_TRP 6 /* ind loop, trap */ +#define I_M_XOP 037 /* XOP: code */ +#define I_V_XOP 6 +#define I_GETXOP(x) (((x) >> I_V_XOP) & I_M_XOP) /* IOT return codes */ #define IOT_V_REASON 16 /* set reason */ +#define IORETURN(f,v) ((f)? (v): SCPE_OK) /* stop on error */ /* IOT fields */ @@ -137,14 +151,14 @@ #define iopC 2 #define iopP 3 -/* Range of implemented device numbers */ +/* Device numbers */ #define DEV_LOW 010 /* lowest intr dev */ -#define DEV_HIGH 033 /* highest intr dev */ +#define DEV_HIGH 051 /* highest intr dev */ #define DEV_MDV 001 /* multiply/divide */ +#define DEV_MAP 003 /* MMPU control */ +#define DEV_ECC 002 /* ECC memory control */ #define DEV_CPU 077 /* CPU control */ - -#define IORETURN(f,v) ((f)? (v): SCPE_OK) /* stop on error */ /* I/O structure @@ -174,11 +188,14 @@ struct ndev { #define INT_V_CLK 7 /* clock */ #define INT_V_PTR 8 /* paper tape reader */ #define INT_V_PTP 9 /* paper tape punch */ -#define INT_V_TTI 10 /* keyboard */ -#define INT_V_TTO 11 /* terminal */ -#define INT_V_STK 13 /* stack overflow */ -#define INT_V_NO_ION_PENDING 14 /* ion delay */ -#define INT_V_ION 15 /* interrupts on */ +#define INT_V_PLT 10 /* plotter */ +#define INT_V_TTI 11 /* keyboard */ +#define INT_V_TTO 12 /* terminal */ +#define INT_V_TTI1 13 /* second keyboard */ +#define INT_V_TTO1 14 /* second terminal */ +#define INT_V_STK 15 /* stack overflow */ +#define INT_V_NO_ION_PENDING 16 /* ion delay */ +#define INT_V_ION 17 /* interrupts on */ #define INT_DKP (1 << INT_V_DKP) #define INT_DSK (1 << INT_V_DSK) @@ -187,8 +204,11 @@ struct ndev { #define INT_CLK (1 << INT_V_CLK) #define INT_PTR (1 << INT_V_PTR) #define INT_PTP (1 << INT_V_PTP) +#define INT_PLT (1 << INT_V_PLT) #define INT_TTI (1 << INT_V_TTI) #define INT_TTO (1 << INT_V_TTO) +#define INT_TTI1 (1 << INT_V_TTI1) +#define INT_TTO1 (1 << INT_V_TTO1) #define INT_STK (1 << INT_V_STK) #define INT_NO_ION_PENDING (1 << INT_V_NO_ION_PENDING) #define INT_ION (1 << INT_V_ION) @@ -204,10 +224,12 @@ struct ndev { #define PI_CLK 0000004 #define PI_PTR 0000020 #define PI_PTP 0000004 +#define PI_PLT 0000010 #define PI_TTI 0000002 #define PI_TTO 0000001 +#define PI_TTI1 PI_TTI +#define PI_TTO1 PI_TTO /* #define PI_CDR 0000040 */ /* #define PI_DCM 0100000 */ /* #define PI_CAS 0000040 */ -/* #define PI_PLT 0000010 */ /* #define PI_ADCV 0000002 */ diff --git a/nova_dkp.c b/nova_dkp.c index 14b4192c..c6efac72 100644 --- a/nova_dkp.c +++ b/nova_dkp.c @@ -25,11 +25,12 @@ dkp moving head disk + 12-Dec-00 RMS Added Eclipse support from Charles Owen 15-Oct-00 RMS Editorial changes 14-Apr-99 RMS Changed t_addr to unsigned 15-Sep-97 RMS Fixed bug in DIB/DOB for new disks - 15-Sep-97 RMS Fixed bug in cylinder extraction (found by Dutch Owen) - 10-Sep-97 RMS Fixed bug in error reporting (found by Dutch Owen) + 15-Sep-97 RMS Fixed bug in cylinder extraction (found by Charles Owen) + 10-Sep-97 RMS Fixed bug in error reporting (found by Charles Owen) 25-Nov-96 RMS Defaults to autosize 29-Jun-96 RMS Added unit disable support */ @@ -275,17 +276,18 @@ int32 dkp_fccy = 0; /* flags/cylinder */ int32 dkp_sta = 0; /* status register */ int32 dkp_swait = 100; /* seek latency */ int32 dkp_rwait = 100; /* rotate latency */ +static unsigned int16 tbuf[DKP_NUMWD]; /* transfer buffer */ t_stat dkp_svc (UNIT *uptr); t_stat dkp_reset (DEVICE *dptr); t_stat dkp_boot (int32 unitno); t_stat dkp_attach (UNIT *uptr, char *cptr); t_stat dkp_go (void); t_stat dkp_set_size (UNIT *uptr, int32 value); -extern t_stat sim_activate (UNIT *uptr, int32 delay); -extern t_stat sim_cancel (UNIT *uptr); -extern int32 sim_is_active (UNIT *uptr); -extern size_t fxread (void *bptr, size_t size, size_t count, FILE *fptr); -extern size_t fxwrite (void *bptr, size_t size, size_t count, FILE *fptr); +#if defined (ECLIPSE) +extern int32 MapAddr (int32 map, int32 addr); +#else +#define MapAddr(m,a) (a) +#endif /* DKP data structures @@ -542,24 +544,16 @@ return TRUE; /* no error */ else, do read or write If controller was busy, clear busy, set done, interrupt - NXM calculation: this takes advantage of the 4KW granularity of - memory, versus the 4KW maximum transfer size. The end address - is calculated as an absolute value; thus it may be ok, non- - existant, or greater than 32KW (wraps to first bank). - - start addr end addr wc wc1 - ok ok unchanged 0 - ok nxm MEMSIZE-dkp_ma < 0 - ok wrapped MEMSIZE-dkp_ma dkp_ma+wc mod 32K - nxm ok impossible - nxm nxm < 0 < 0 - nxm wrapped < 0 dkp-ma+wc mod 32K + Memory access: sectors are read into/written from an intermediate + buffer to allow word-by-word mapping of memory addresses on the + Eclipse. This allows each word written to memory to be tested + for out of range. */ -t_stat dkp_svc (uptr) -UNIT *uptr; +t_stat dkp_svc (UNIT *uptr) { -int32 sc, sa, xcsa, wc, wc1, awc, bda; +int32 sc, sa, xcsa, awc, bda; +int32 sx, dx, pa; int32 dtype, u, err, newsect, newsurf; t_stat rval; @@ -589,40 +583,33 @@ else if (GET_CYL (dkp_fccy, dtype) != uptr -> CYL) /* address error? */ else { sc = 16 - GET_COUNT (dkp_ussc); /* get sector count */ sa = GET_SA (uptr -> CYL, GET_SURF (dkp_ussc, dtype), - GET_SECT (dkp_ussc, dtype), dtype); /* get disk block */ + GET_SECT (dkp_ussc, dtype), dtype); /* get disk block */ xcsa = GET_SA (uptr -> CYL + 1, 0, 0, dtype); /* get next cyl addr */ if ((sa + sc) > xcsa ) { /* across cylinder? */ sc = xcsa - sa; /* limit transfer */ dkp_sta = dkp_sta | STA_XCY; } /* xcyl error */ - wc = sc * DKP_NUMWD; /* convert blocks */ bda = sa * DKP_NUMWD * sizeof (short); /* to words, bytes */ - if (((t_addr) (dkp_ma + wc)) <= MEMSIZE) wc1 = 0; /* xfer fit? */ - else { wc = MEMSIZE - dkp_ma; /* calculate xfer */ - wc1 = (dkp_ma + wc) - MAXMEMSIZE; } /* calculate wrap */ err = fseek (uptr -> fileref, bda, SEEK_SET); /* position drive */ if (uptr -> FUNC == FCCY_READ) { /* read? */ - if ((wc > 0) && (err == 0)) { /* start in memory? */ - awc = fxread (&M[dkp_ma], sizeof (int16), wc, uptr -> fileref); - for ( ; awc < wc; awc++) M[(dkp_ma + awc) & AMASK] = 0; - err = ferror (uptr -> fileref); - dkp_ma = (dkp_ma + wc) & AMASK; } - if ((wc1 > 0) && (err == 0)) { /* memory wrap? */ - awc = fxread (&M[0], sizeof (int16), wc1, uptr -> fileref); - for ( ; awc < wc1; awc++) M[0 + awc] = 0; - err = ferror (uptr -> fileref); - dkp_ma = (dkp_ma + wc1) & AMASK; } } + for (sx = 0; sx < sc; sx++) { /* loop thru sectors */ + awc = fxread (&tbuf, sizeof(uint16), DKP_NUMWD, uptr -> fileref); + for ( ; awc < DKP_NUMWD; awc++) tbuf[awc] = 0; + if (err = ferror (uptr -> fileref)) break; + for (dx = 0; dx < DKP_NUMWD; dx++) { /* loop thru buffer */ + pa = MapAddr (0, dkp_ma); + if (MEM_ADDR_OK (pa)) M[pa] = tbuf[dx]; + dkp_ma = (dkp_ma + 1) & AMASK; } } } if (uptr -> FUNC == FCCY_WRITE) { /* write? */ - if ((wc > 0) && (err == 0)) { /* start in memory? */ - fxwrite (&M[dkp_ma], sizeof (int16), wc, uptr -> fileref); - err = ferror (uptr -> fileref); - dkp_ma = (dkp_ma + wc + 2) & AMASK; } - if ((wc1 > 0) && (err == 0)) { /* memory wrap? */ - fxwrite (&M[0], sizeof (int16), wc1, uptr -> fileref); - err = ferror (uptr -> fileref); - dkp_ma = (dkp_ma + wc1) & AMASK; } } + for (sx = 0; sx < sc; sx++) { /* loop thru sectors */ + for (dx = 0; dx < DKP_NUMWD; dx++) { /* loop into buffer */ + pa = MapAddr (0, dkp_ma); + tbuf[dx] = M[pa]; + dkp_ma = (dkp_ma + 1) & AMASK; } + fxwrite (&tbuf, sizeof(int16), DKP_NUMWD, uptr -> fileref); + if (err = ferror (uptr -> fileref)) break; } } if (err != 0) { perror ("DKP I/O error"); @@ -646,8 +633,7 @@ return rval; /* Reset routine */ -t_stat dkp_reset (dptr) -DEVICE *dptr; +t_stat dkp_reset (DEVICE *dptr) { int32 u; UNIT *uptr; diff --git a/nova_dsk.c b/nova_dsk.c index b291c45c..64fa3be4 100644 --- a/nova_dsk.c +++ b/nova_dsk.c @@ -25,6 +25,7 @@ dsk fixed head disk + 10-Dec-00 RMS Added Eclipse support 15-Oct-00 RMS Editorial changes 14-Apr-99 RMS Changed t_addr to unsigned @@ -85,8 +86,11 @@ int32 dsk_time = 100; /* time per sector */ t_stat dsk_svc (UNIT *uptr); t_stat dsk_reset (DEVICE *dptr); t_stat dsk_boot (int32 unitno); -extern t_stat sim_activate (UNIT *uptr, int32 delay); -extern t_stat sim_cancel (UNIT *uptr); +#if defined (ECLIPSE) +extern int32 MapAddr (int32 map, int32 addr); +#else +#define MapAddr(m,a) (a) +#endif /* DSK data structures @@ -170,8 +174,7 @@ return rval; t_stat dsk_svc (UNIT *uptr) { -int32 i, da; -t_addr j; +int32 i, da, pa; dev_busy = dev_busy & ~INT_DSK; /* clear busy */ dev_done = dev_done | INT_DSK; /* set done */ @@ -184,14 +187,14 @@ if ((uptr -> flags & UNIT_BUF) == 0) { /* not buf? abort */ da = dsk_da * DSK_NUMWD; /* calc disk addr */ if (uptr -> FUNC == iopS) { /* read? */ for (i = 0; i < DSK_NUMWD; i++) { /* copy sector */ - j = (dsk_ma + i) & AMASK; - if (MEM_ADDR_OK (j)) - M[j] = *(((int16 *) uptr -> filebuf) + da + i); } + pa = MapAddr (0, (dsk_ma + i) & AMASK); /* map address */ + if (MEM_ADDR_OK (pa)) M[pa] = + *(((int16 *) uptr -> filebuf) + da + i); } dsk_ma = (dsk_ma + DSK_NUMWD) & AMASK; } if (uptr -> FUNC == iopP) { /* write? */ for (i = 0; i < DSK_NUMWD; i++) { /* copy sector */ - *(((int16 *) uptr -> filebuf) + da + i) = - M[(dsk_ma + i) & AMASK]; } + pa = MapAddr (0, (dsk_ma + i) & AMASK); /* map address */ + *(((int16 *) uptr -> filebuf) + da + i) = M[pa]; } dsk_ma = (dsk_ma + DSK_NUMWD + 3) & AMASK; } dsk_stat = 0; /* set status */ diff --git a/nova_lp.c b/nova_lp.c index ca581236..13506b25 100644 --- a/nova_lp.c +++ b/nova_lp.c @@ -1,6 +1,6 @@ /* nova_lp.c: NOVA line printer simulator - Copyright (c) 1993-1999, Robert M. Supnik + Copyright (c) 1993-2000, 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"), @@ -32,8 +32,6 @@ extern int32 int_req, dev_busy, dev_done, dev_disable; int32 lpt_stopioe = 0; /* stop on error */ t_stat lpt_svc (UNIT *uptr); t_stat lpt_reset (DEVICE *dptr); -extern t_stat sim_activate (UNIT *uptr, int32 delay); -extern t_stat sim_cancel (UNIT *uptr); /* LPT data structures diff --git a/nova_mta.c b/nova_mta.c index 32e4fb8b..a6748c2d 100644 --- a/nova_mta.c +++ b/nova_mta.c @@ -25,7 +25,9 @@ mta magnetic tape + 10-Dec-00 RMS Added Eclipse support from Charles Owen 15-Oct-00 RMS Editorial changes + 11-Nov-98 CEO Removed clear of mta_ma on iopC 04-Oct-98 RMS V2.4 magtape format 18-Jan-97 RMS V2.3 magtape format 29-Jun-96 RMS Added unit disable support @@ -146,11 +148,11 @@ t_stat mta_detach (UNIT *uptr); int32 mta_updcsta (UNIT *uptr); void mta_upddsta (UNIT *uptr, int32 newsta); t_stat mta_vlock (UNIT *uptr, int32 val); -extern t_stat sim_activate (UNIT *uptr, int32 delay); -extern t_stat sim_cancel (UNIT *uptr); -extern int32 sim_is_active (UNIT *uptr); -extern size_t fxread (void *bptr, size_t size, size_t count, FILE *fptr); -extern size_t fxwrite (void *bptr, size_t size, size_t count, FILE *fptr); +#if defined (ECLIPSE) +extern int32 MapAddr (int32 map, int32 addr); +#else +#define MapAddr(m,a) (a) +#endif static const int ctype[32] = { /* c vs r timing */ 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, @@ -299,7 +301,7 @@ case iopC: /* clear */ dev_busy = dev_busy & ~INT_MTA; /* clear busy */ dev_done = dev_done & ~INT_MTA; /* clear done */ int_req = int_req & ~INT_MTA; /* clear int */ - mta_sta = mta_cu = mta_ma = 0; /* clear registers */ + mta_sta = mta_cu = 0; /* clear registers */ mta_updcsta (&mta_unit[0]); /* update status */ break; } /* end case pulse */ return rval; @@ -313,7 +315,7 @@ return rval; t_stat mta_svc (UNIT *uptr) { -int32 c, i, p, u, err; +int32 c, i, p, u, pa, err; t_stat rval; t_mtrlnt cbc, tbc, wc; unsigned int16 c1, c2; @@ -377,7 +379,8 @@ case CU_READNS: /* read non-stop */ for (i = p = 0; i < wc; i++) { /* copy buf to mem */ c1 = dbuf[p++]; c2 = dbuf[p++]; - if (MEM_ADDR_OK (mta_ma)) M[mta_ma] = (c1 << 8) | c2; + pa = MapAddr (0, mta_ma); /* map address */ + if (MEM_ADDR_OK (pa)) M[pa] = (c1 << 8) | c2; mta_ma = (mta_ma + 1) & AMASK; } mta_wc = (mta_wc + wc) & DMASK; uptr -> pos = uptr -> pos + ((tbc + 1) & ~1) + @@ -388,9 +391,10 @@ case CU_WRITE: /* write */ fseek (uptr -> fileref, uptr -> pos, SEEK_SET); tbc = wc * 2; /* io byte count */ fxwrite (&tbc, sizeof (t_mtrlnt), 1, uptr -> fileref); - for (i = p = 0; i < wc; i++) { /* copy to buffer */ - dbuf[p++] = (M[mta_ma] >> 8) & 0377; - dbuf[p++] = M[mta_ma] & 0377; + for (i = p = 0; i < wc; i++) { /* copy to buffer */ + pa = MapAddr (0, mta_ma); /* map address */ + dbuf[p++] = (M[pa] >> 8) & 0377; + dbuf[p++] = M[pa] & 0377; mta_ma = (mta_ma + 1) & AMASK; } fxwrite (dbuf, sizeof (int8), tbc, uptr -> fileref); fxwrite (&tbc, sizeof (t_mtrlnt), 1, uptr -> fileref); diff --git a/nova_plt.c b/nova_plt.c new file mode 100644 index 00000000..4ec0d754 --- /dev/null +++ b/nova_plt.c @@ -0,0 +1,110 @@ +/* nova_plt.c: NOVA plotter simulator + + Copyright (c) 2000, Robert M. Supnik + Written by Bruce Ray and used with his gracious permission. + + 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. +*/ + +#include "nova_defs.h" + +extern int32 int_req, dev_busy, dev_done, dev_disable; +int32 plt_stopioe = 0; /* stop on error */ +t_stat plt_svc (UNIT *uptr); +t_stat plt_reset (DEVICE *dptr); + +/* PLT data structures + + plt_dev PLT device descriptor + plt_unit PLT unit descriptor + plt_reg PLT register list +*/ + +UNIT plt_unit = { + UDATA (&plt_svc, UNIT_SEQ+UNIT_ATTABLE, 0), SERIAL_OUT_WAIT }; + +REG plt_reg[] = { + { ORDATA (BUF, plt_unit.buf, 8) }, + { FLDATA (BUSY, dev_busy, INT_V_PLT) }, + { FLDATA (DONE, dev_done, INT_V_PLT) }, + { FLDATA (DISABLE, dev_disable, INT_V_PLT) }, + { FLDATA (INT, int_req, INT_V_PLT) }, + { DRDATA (POS, plt_unit.pos, 31), PV_LEFT }, + { DRDATA (TIME, plt_unit.wait, 24), PV_LEFT }, + { FLDATA (STOP_IOE, plt_stopioe, 0) }, + { NULL } }; + +DEVICE plt_dev = { + "PLT", &plt_unit, plt_reg, NULL, + 1, 10, 31, 1, 8, 8, + NULL, NULL, &plt_reset, + NULL, NULL, NULL }; + +/* plotter: IOT routine */ + +int32 plt (int32 pulse, int32 code, int32 AC) +{ +if (code == ioDOA) plt_unit.buf = AC & 0377; +switch (pulse) { /* decode IR<8:9> */ +case iopS: /* start */ + dev_busy = dev_busy | INT_PLT; /* set busy */ + dev_done = dev_done & ~INT_PLT; /* clear done, int */ + int_req = int_req & ~INT_PLT; + sim_activate (&plt_unit, plt_unit.wait); /* activate unit */ + break; +case iopC: /* clear */ + dev_busy = dev_busy & ~INT_PLT; /* clear busy */ + dev_done = dev_done & ~INT_PLT; /* clear done, int */ + int_req = int_req & ~INT_PLT; + sim_cancel (&plt_unit); /* deactivate unit */ + break; } /* end switch */ +return 0; +} + +/* Unit service */ + +t_stat plt_svc (UNIT *uptr) +{ +dev_busy = dev_busy & ~INT_PLT; /* clear busy */ +dev_done = dev_done | INT_PLT; /* set done */ +int_req = (int_req & ~INT_DEV) | (dev_done & ~dev_disable); +if ((plt_unit.flags & UNIT_ATT) == 0) /* attached? */ + return IORETURN (plt_stopioe, SCPE_UNATT); +if (putc (plt_unit.buf, plt_unit.fileref) == EOF) { + perror ("PLT I/O error"); + clearerr (plt_unit.fileref); + return SCPE_IOERR; } +plt_unit.pos = plt_unit.pos + 1; +return SCPE_OK; +} + +/* Reset routine */ + +t_stat plt_reset (DEVICE *dptr) +{ +plt_unit.buf = 0; +dev_busy = dev_busy & ~INT_PLT; /* clear busy */ +dev_done = dev_done & ~INT_PLT; /* clear done, int */ +int_req = int_req & ~INT_PLT; +sim_cancel (&plt_unit); /* deactivate unit */ +return SCPE_OK; +} diff --git a/nova_pt.c b/nova_pt.c index b5a36a3e..3cef9dae 100644 --- a/nova_pt.c +++ b/nova_pt.c @@ -1,6 +1,6 @@ /* nova_pt.c: NOVA paper tape read/punch simulator - Copyright (c) 1993-1999, Robert M. Supnik + Copyright (c) 1993-2000, 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"), @@ -35,8 +35,6 @@ t_stat ptr_svc (UNIT *uptr); t_stat ptp_svc (UNIT *uptr); t_stat ptr_reset (DEVICE *dptr); t_stat ptp_reset (DEVICE *dptr); -extern t_stat sim_activate (UNIT *uptr, int32 delay); -extern t_stat sim_cancel (UNIT *uptr); /* PTR data structures diff --git a/nova_sys.c b/nova_sys.c index cf6a816b..4eed75c6 100644 --- a/nova_sys.c +++ b/nova_sys.c @@ -23,6 +23,9 @@ 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. + 22-Dec-00 RMS Added second terminal support + 10-Dec-00 RMS Added Eclipse support + 08-Dec-00 BKR Added plotter support 30-Oct-00 RMS Added support for examine to file 15-Oct-00 RMS Added stack, byte, trap instructions 14-Apr-99 RMS Changed t_addr to unsigned @@ -35,8 +38,13 @@ extern DEVICE cpu_dev; extern UNIT cpu_unit; +#if defined (ECLIPSE) +extern DEVICE map_dev; +#endif extern DEVICE ptr_dev, ptp_dev; +extern DEVICE plt_dev; extern DEVICE tti_dev, tto_dev; +extern DEVICE tti1_dev, tto1_dev; extern DEVICE clk_dev, lpt_dev; extern DEVICE dkp_dev, dsk_dev; extern DEVICE mta_dev; @@ -54,16 +62,28 @@ extern int32 saved_PC; sim_load binary loader */ +#if defined (ECLIPSE) +char sim_name[] = "ECLIPSE"; +#else char sim_name[] = "NOVA"; +#endif REG *sim_PC = &cpu_reg[0]; int32 sim_emax = 4; -DEVICE *sim_devices[] = { &cpu_dev, - &ptr_dev, &ptp_dev, &tti_dev, &tto_dev, - &clk_dev, &lpt_dev, &dsk_dev, &dkp_dev, - &mta_dev, NULL }; +DEVICE *sim_devices[] = { + &cpu_dev, +#if defined (ECLIPSE) + &map_dev, +#endif + &ptr_dev, &ptp_dev, + &tti_dev, &tto_dev, + &tti1_dev, &tto1_dev, + &clk_dev, &plt_dev, + &lpt_dev, &dsk_dev, + &dkp_dev, &mta_dev, + NULL }; const char *sim_stop_messages[] = { "Unknown error", @@ -72,7 +92,9 @@ const char *sim_stop_messages[] = { "Breakpoint", "Nested indirect address limit exceeded", "Nested indirect interrupt address limit exceeded", - "Nested indirect trap address limit exceeded" }; + "Nested indirect trap address limit exceeded", + "Read breakpoint", + "Write breakpoint" }; /* Binary loader @@ -175,15 +197,24 @@ return ((state == 0) || (state == 8))? SCPE_OK: SCPE_FMT; /* Symbol tables */ #define I_V_FL 18 /* flag bits */ -#define I_M_FL 07 /* flag width */ -#define I_V_NPN 0 /* no operands */ -#define I_V_R 1 /* reg */ -#define I_V_D 2 /* device */ -#define I_V_RD 3 /* reg,device */ -#define I_V_M 4 /* mem addr */ -#define I_V_RM 5 /* reg, mem addr */ -#define I_V_RR 6 /* operate */ -#define I_V_BY 7 /* byte pointer */ +#define I_M_FL 037 /* flag width */ +#define I_V_NPN 000 /* no operands */ +#define I_V_R 001 /* reg */ +#define I_V_D 002 /* device */ +#define I_V_RD 003 /* reg,device */ +#define I_V_M 004 /* mem addr */ +#define I_V_RM 005 /* reg,mem addr */ +#define I_V_RR 006 /* operate */ +#define I_V_BY 007 /* Nova byte pointer */ +#define I_V_2AC 010 /* reg,reg */ +#define I_V_RSI 011 /* reg,short imm */ +#define I_V_LI 012 /* long imm */ +#define I_V_RLI 013 /* reg,long imm */ +#define I_V_LM 014 /* long mem addr */ +#define I_V_RLM 015 /* reg,long mem addr */ +#define I_V_FRM 016 /* flt reg,long mem addr */ +#define I_V_FST 017 /* flt long mem, status */ +#define I_V_XP 020 /* XOP */ #define I_NPN (I_V_NPN << I_V_FL) #define I_R (I_V_R << I_V_FL) #define I_D (I_V_D << I_V_FL) @@ -192,14 +223,64 @@ return ((state == 0) || (state == 8))? SCPE_OK: SCPE_FMT; #define I_RM (I_V_RM << I_V_FL) #define I_RR (I_V_RR << I_V_FL) #define I_BY (I_V_BY << I_V_FL) +#define I_2AC (I_V_2AC << I_V_FL) +#define I_RSI (I_V_RSI << I_V_FL) +#define I_LI (I_V_LI << I_V_FL) +#define I_RLI (I_V_RLI << I_V_FL) +#define I_LM (I_V_LM << I_V_FL) +#define I_RLM (I_V_RLM << I_V_FL) +#define I_FRM (I_V_FRM << I_V_FL) +#define I_FST (I_V_FST << I_V_FL) +#define I_XP (I_V_XP << I_V_FL) static const int32 masks[] = { 0177777, 0163777, 0177700, 0163700, -0174000, 0160000, 0103770, 0163477 }; +0174000, 0160000, 0103770, 0163477, +0103777, 0103777, 0177777, 0163777, +0176377, 0162377, 0103777, 0163777, +0100077 }; static const char *opcode[] = { "JMP", "JSR", "ISZ", "DSZ", "LDA", "STA", +#if defined (ECLIPSE) + "ADI", "SBI", "DAD", "DSB", + "IOR", "XOR", "ANC", "XCH", + "SGT", "SGE", "LSH", "DLSH", + "HXL", "HXR", "DHXL", "DHXR", + "BTO", "BTZ", "SBZ", "SZBO", + "LOB", "LRB", "COB", "LDB", + "STB", "PSH", "POP", + "LMP", "SYSC", + "PSHR", "POPB", "BAM", "POPJ", + "RTN", "BLM", "DIVX", + "MUL", "MULS", "DIV", "DIVS", + "SAVE", "RSTR", + "XOP", + "FAS", "FAD", "FSS", "FSD", + "FMS", "FMD", "FDS", "FDD", + "FAMS", "FAMD", "FSMS", "FSMD", + "FMMS", "FMMD", "FDMS", "FDMD", + "FLDS", "FLDD", "FSTS", "FSTD", + "FLAS", "FLMD", "FFAS", "FFMD", + "FNOM", "FRH", "FAB", "FNEG", + "FSCAL", "FEXP", "FINT", "FHLV", + "FNS", "FSA", "FSEQ", "FSNE", + "FSLT", "FSGE", "FSLE", "FSGT", + "FSNM", "FSND", "FSNU", "FSNUD", + "FSNO", "FSNOD", "FSNUO", "FSNER", + "FSST", "FLST", + "FTE", "FTD", "FCLE", + "FPSH", "FPOP", + "FCMP", "FMOV", + "CMV", "CMP", "CTR", "CMT", + "EJMP", "EJSR", "EISZ", "EDSZ", + "ELDA", "ESTA", "ELEF", + "ELDB", "ESTB", "DSPA", + "PSHJ", "CLM", "SNB", + "MSP", "XCT", "HLV", + "IORI", "XORI", "ANDI", "ADDI", +#endif "COM", "COMZ", "COMO", "COMC", "COML", "COMZL", "COMOL", "COMCL", "COMR", "COMZR", "COMOR", "COMCR", @@ -266,10 +347,12 @@ static const char *opcode[] = { "ANDS#", "ANDZS#", "ANDOS#", "ANDCS#", "ION", "IOF", "RDSW", "INTA", "MSKO", "IORST", "HALT", +#if !defined (ECLIPSE) "MUL", "DIV", "MULS", "DIVS", "PSHA", "POPA", "SAV", "RET", "MTSP", "MTFP", "MFSP", "MFFP", "LDB", "STB", +#endif "NIO", "NIOS", "NIOC", "NIOP", "DIA", "DIAS", "DIAC", "DIAP", "DOA", "DOAS", "DOAC", "DOAP", @@ -283,6 +366,44 @@ static const char *opcode[] = { static const opc_val[] = { 0000000+I_M, 0004000+I_M, 0010000+I_M, 0014000+I_M, 0020000+I_RM, 0040000+I_RM, +#if defined (ECLIPSE) + 0100010+I_RSI, 0100110+I_RSI, 0100210+I_2AC, 0100310+I_2AC, + 0100410+I_2AC, 0100510+I_2AC, 0100610+I_2AC, 0100710+I_2AC, + 0101010+I_2AC, 0101110+I_2AC, 0101210+I_RSI, 0101310+I_RSI, + 0101410+I_RSI, 0101510+I_RSI, 0101610+I_RSI, 0101710+I_RSI, + 0102010+I_2AC, 0102110+I_2AC, 0102210+I_2AC, 0102310+I_2AC, + 0102410+I_2AC, 0102510+I_2AC, 0102610+I_2AC, 0102710+I_2AC, + 0103010+I_2AC, 0103110+I_2AC, 0103210+I_2AC, + 0113410+I_NPN, 0103510+I_RSI, + 0103710+I_NPN, 0107710+I_NPN, 0113710+I_NPN, 0117710+I_NPN, + 0127710+I_NPN, 0133710+I_NPN, 0137710+I_NPN, + 0143710+I_NPN, 0147710+I_NPN, 0153710+I_NPN, 0157710+I_NPN, + 0163710+I_LI, 0167710+I_NPN, + 0100030+I_XP, + 0100050+I_2AC, 0100150+I_2AC, 0100250+I_2AC, 0100350+I_2AC, + 0100450+I_2AC, 0100550+I_2AC, 0100650+I_2AC, 0100750+I_2AC, + 0101050+I_FRM, 0101150+I_FRM, 0101250+I_FRM, 0101350+I_FRM, + 0101450+I_FRM, 0101550+I_FRM, 0101650+I_FRM, 0101750+I_FRM, + 0102050+I_FRM, 0102150+I_FRM, 0102250+I_FRM, 0102350+I_FRM, + 0102450+I_2AC, 0102550+I_FRM, 0102650+I_2AC, 0102750+I_FRM, + 0103050+I_R, 0123050+I_R, 0143050+I_R, 0163050+I_R, + 0103150+I_R, 0123150+I_R, 0143150+I_R, 0163150+I_R, + 0103250+I_NPN, 0107250+I_NPN, 0113250+I_NPN, 0117250+I_NPN, + 0123250+I_NPN, 0127250+I_NPN, 0133250+I_NPN, 0137250+I_NPN, + 0143250+I_NPN, 0147250+I_NPN, 0153250+I_NPN, 0157250+I_NPN, + 0163250+I_NPN, 0167250+I_NPN, 0173250+I_NPN, 0177250+I_NPN, + 0103350+I_FST, 0123350+I_FST, + 0143350+I_NPN, 0147350+I_NPN, 0153350+I_NPN, + 0163350+I_NPN, 0167350+I_NPN, + 0103450+I_2AC, 0103550+I_2AC, + 0153650+I_NPN, 0157650+I_NPN, 0163650+I_NPN, 0167650+I_NPN, + 0102070+I_LM, 0106070+I_LM, 0112070+I_LM, 0116070+I_LM, + 0122070+I_RLM, 0142070+I_RLM, 0162070+I_RLM, + 0102170+I_RLM, 0122170+I_RLM, 0142170+I_RLM, + 0102270+I_LM, 0102370+I_2AC, 0102770+I_2AC, + 0103370+I_R, 0123370+I_R, 0143370+I_R, + 0103770+I_RLI, 0123770+I_RLI, 0143770+I_RLI, 0163770+I_RLI, +#endif 0100000+I_RR, 0100020+I_RR, 0100040+I_RR, 0100060+I_RR, 0100100+I_RR, 0100120+I_RR, 0100140+I_RR, 0100160+I_RR, 0100200+I_RR, 0100220+I_RR, 0100240+I_RR, 0100260+I_RR, @@ -349,10 +470,12 @@ static const opc_val[] = { 0103710+I_RR, 0103730+I_RR, 0103750+I_RR, 0103770+I_RR, 0060177+I_NPN, 0060277+I_NPN, 0060477+I_R, 0061477+I_R, 0062077+I_R, 0062677+I_NPN, 0063077+I_NPN, +#if !defined (ECLIPSE) 0073301+I_NPN, 0073101+I_NPN, 0077201+I_NPN, 0077001+I_NPN, 0061401+I_R, 0061601+I_R, 0062401+I_NPN, 0062601+I_NPN, 0061001+I_R, 0060001+I_R, 0061201+I_R, 0060201+I_R, 0060401+I_BY, 0062001+I_BY, +#endif 0060000+I_D, 0060100+I_D, 0060200+I_D, 0060300+I_D, 0060400+I_RD, 0060500+I_RD, 0060600+I_RD, 0060700+I_RD, 0061000+I_RD, 0061100+I_RD, 0061200+I_RD, 0061300+I_RD, @@ -368,13 +491,21 @@ static const char *skip[] = { NULL }; static const char *device[] = { +#if defined (ECLIPSE) + "ERCC", "MAP", +#endif "TTI", "TTO", "PTR", "PTP", "RTC", "PLT", "CDR", "LPT", - "DSK", "MTA", "DCM", "ADCV", "DKP", "CAS", "CPU", + "DSK", "MTA", "DCM", "ADCV", "DKP", "CAS", + "TTI1", "TTO1", "CPU", NULL }; static const int32 dev_val[] = { +#if defined (ECLIPSE) + 002, 003, +#endif 010, 011, 012, 013, 014, 015, 016, 017, - 020, 022, 024, 030, 033, 034, 077, + 020, 022, 024, 030, 033, 034, + 050, 051, 077, -1 }; /* Address decode @@ -382,35 +513,41 @@ static const int32 dev_val[] = { Inputs: *of = output stream addr = current PC - inst = instruction to decode + ind = indirect flag + mode = addressing mode + disp = displacement + ext = true if extended address cflag = true if decoding for CPU Outputs: return = error code */ -t_stat fprint_addr (FILE *of, t_addr addr, int32 inst, int32 cflag) +t_stat fprint_addr (FILE *of, t_addr addr, int32 ind, int32 mode, + int32 disp, t_bool ext, int32 cflag) { -int32 disp; +int32 dsign, dmax; -if (inst & I_IND) fprintf (of, "@"); /* indirect? */ -disp = I_GETDISP (inst); /* displacement */ -switch (I_GETMODE (inst)) { /* mode */ -case 0: /* page zero */ +if (ext) dmax = AMASK + 1; /* get max disp */ +else dmax = I_M_DISP + 1; +dsign = dmax >> 1; /* get disp sign */ +if (ind) fprintf (of, "@"); /* indirect? */ +switch (mode & 03) { /* mode */ +case 0: /* absolute */ fprintf (of, "%-o", disp); break; case 1: /* PC rel */ - if (disp & DISPSIGN) { - if (cflag) fprintf (of, "%-o", (addr + 0177400 + disp) & AMASK); - else fprintf (of, ".-%-o", 0400 - disp); } + if (disp & dsign) { + if (cflag) fprintf (of, "%-o", (addr - (dmax - disp)) & AMASK); + else fprintf (of, ".-%-o", dmax - disp); } else { if (cflag) fprintf (of, "%-o", (addr + disp) & AMASK); else fprintf (of, ".+%-o", disp); } break; case 2: /* AC2 rel */ - if (disp & DISPSIGN) fprintf (of, "-%-o,2", 0400 - disp); + if (disp & dsign) fprintf (of, "-%-o,2", dmax - disp); else fprintf (of, "%-o,2", disp); break; case 3: /* AC3 rel */ - if (disp & DISPSIGN) fprintf (of, "-%-o,3", 0400 - disp); + if (disp & dsign) fprintf (of, "-%-o,3", dmax - disp); else fprintf (of, "%-o,3", disp); break; } /* end switch */ return SCPE_OK; @@ -431,7 +568,9 @@ return SCPE_OK; t_stat fprint_sym (FILE *of, t_addr addr, t_value *val, UNIT *uptr, int32 sw) { -int32 cflag, i, j, c1, c2, inst, dv, src, dst, skp, dev, byac; +int32 cflag, i, j, c1, c2, inst, dv, src, dst, skp; +int32 ind, mode, disp, dev; +int32 byac, extind, extdisp, xop; cflag = (uptr == NULL) || (uptr == &cpu_unit); c1 = (val[0] >> 8) & 0177; @@ -454,7 +593,14 @@ for (i = 0; opc_val[i] >= 0; i++) { /* loop thru ops */ src = I_GETSRC (inst); /* opr fields */ dst = I_GETDST (inst); skp = I_GETSKP (inst); + ind = inst & I_IND; /* mem ref fields */ + mode = I_GETMODE (inst); + disp = I_GETDISP (inst); dev = I_GETDEV (inst); /* IOT fields */ + byac = I_GETPULSE (inst); /* byte fields */ + xop = I_GETXOP (inst); /* XOP fields */ + extind = val[1] & A_IND; /* extended fields */ + extdisp = val[1] & AMASK; for (dv = 0; (dev_val[dv] >= 0) && (dev_val[dv] != dev); dv++) ; switch (j) { /* switch on class */ @@ -476,19 +622,49 @@ for (i = 0; opc_val[i] >= 0; i++) { /* loop thru ops */ break; case I_V_M: /* addr only */ fprintf (of, "%s ", opcode[i]); - fprint_addr (of, addr, inst, cflag); + fprint_addr (of, addr, ind, mode, disp, FALSE, cflag); break; case I_V_RM: /* reg, addr */ fprintf (of, "%s %-o,", opcode[i], dst); - fprint_addr (of, addr, inst, cflag); + fprint_addr (of, addr, ind, mode, disp, FALSE, cflag); break; case I_V_RR: /* operate */ fprintf (of, "%s %-o,%-o", opcode[i], src, dst); if (skp) fprintf (of, ",%s", skip[skp-1]); break; case I_V_BY: /* byte */ - byac = I_GETPULSE (inst); /* src = pulse */ fprintf (of, "%s %-o,%-o", opcode[i], byac, dst); + break; + case I_V_2AC: /* reg, reg */ + fprintf (of, "%s %-o,%-o", opcode[i], src, dst); + break; + case I_V_RSI: /* reg, short imm */ + fprintf (of, "%s %-o,%-o", opcode[i], src + 1, dst); + break; + case I_V_LI: /* long imm */ + fprintf (of, "%s %-o", opcode[i], val[1]); + return -1; + case I_V_RLI: /* reg, long imm */ + fprintf (of, "%s %-o,%-o", opcode[i], val[1], dst); + return -1; + case I_V_LM: /* long addr */ + fprintf (of, "%s ", opcode[i]); + fprint_addr (of, addr, extind, mode, extdisp, TRUE, cflag); + return -1; + case I_V_RLM: /* reg, long addr */ + fprintf (of, "%s %-o,", opcode[i], dst); + fprint_addr (of, addr, extind, mode, extdisp, TRUE, cflag); + return -1; + case I_V_FRM: /* flt reg, long addr */ + fprintf (of, "%s %-o,", opcode[i], dst); + fprint_addr (of, addr, extind, src, extdisp, TRUE, cflag); + return -1; + case I_V_FST: /* flt status */ + fprintf (of, "%s ", opcode[i]); + fprint_addr (of, addr, extind, dst, extdisp, AMASK + 1, cflag); + return -1; + case I_V_XP: /* XOP */ + fprintf (of, "%s %-o,%-o,%-o", opcode[i], src, dst, xop); break; } /* end case */ return SCPE_OK; } /* end if */ } /* end for */ @@ -500,8 +676,9 @@ return SCPE_ARG; Inputs: *cptr = pointer to input string addr = current PC + ext = extended address cflag = true if parsing for CPU - *val = pointer to output value + val[3] = output array Outputs: optr = pointer to next char in input string NULL if error @@ -514,22 +691,26 @@ return SCPE_ARG; #define A_SI 020 /* sign seen */ #define A_MI 040 /* - seen */ -char *get_addr (char *cptr, t_addr addr, int32 cflag, int32 *val) +char *get_addr (char *cptr, t_addr addr, t_bool ext, int32 cflag, int32 *val) { int32 d, r, x, pflag; -t_addr sd; char gbuf[CBUFSIZE]; +int32 dmax, dsign; -*val = 0; /* clear result */ -d = 0; /* default no num */ -x = 1; /* default PC rel */ +if (ext) dmax = AMASK + 1; /* get max disp */ +else dmax = I_M_DISP + 1; +dsign = dmax >> 1; /* get disp sign */ +val[0] = 0; /* no indirect */ +val[1] = 0; /* PC rel */ +val[2] = 0; /* no addr */ pflag = cflag & A_FL; /* isolate flag */ if (*cptr == '@') { /* indirect? */ - *val = I_IND; + val[0] = 1; cptr++; } if (*cptr == '.') { /* relative? */ pflag = pflag | A_PER; + x = 1; /* "index" is PC */ cptr++; } if (*cptr == '+') { /* + sign? */ pflag = pflag | A_SI; @@ -541,8 +722,7 @@ if (*cptr != 0) { /* number? */ cptr = get_glyph (cptr, gbuf, ','); /* get glyph */ d = get_uint (gbuf, 8, AMASK, &r); if (r != SCPE_OK) return NULL; - pflag = pflag | A_NUM; - sd = (pflag & A_MI)? -d: d; } + pflag = pflag | A_NUM; } if (*cptr != 0) { /* index? */ cptr = get_glyph (cptr, gbuf, 0); /* get glyph */ x = get_uint (gbuf, 8, I_M_DST, &r); @@ -551,32 +731,62 @@ if (*cptr != 0) { /* index? */ /* Address parse, continued */ -switch (pflag & ~A_MI) { /* case on flags */ -case A_NUM: case A_NUM+A_SI: /* ~CPU, (+/-) num */ - if (sd <= I_M_DISP) *val = *val + sd; +switch (pflag) { /* case on flags */ +case A_NUM: case A_NUM+A_SI: /* ~CPU, (+)num */ + if (d < dmax) val[2] = d; else return NULL; break; -case A_NUM+A_FL: case A_NUM+A_SI+A_FL: /* CPU, (+/-) num */ - if (sd <= I_M_DISP) *val = *val + sd; - else if (((sd >= ((addr - 0200) & AMASK)) && - (sd <= ((addr + 0177) & AMASK))) || - (sd >= (addr + 077600))) - *val = *val + 0400 + ((sd - addr) & I_M_DISP); +case A_NUM+A_FL: case A_NUM+A_SI+A_FL: /* CPU, (+)num */ + if (d < dmax) val[2] = d; + else if (((d >= (((int32) addr - dsign) & AMASK)) && + (d < (((int32) addr + dsign) & AMASK))) || + (d >= ((int32) addr + (-dsign & AMASK)))) { + val[1] = 1; /* PC rel */ + val[2] = (d - addr) & (dmax - 1); } else return NULL; break; -case A_PER: case A_PER+A_FL: /* .+/- num */ -case A_PER+A_SI+A_NUM: case A_PER+A_SI+A_NUM+A_FL: -case A_NX+A_NUM: case A_NX+A_NUM+A_FL: /* (+/-) num, ndx */ -case A_NX+A_SI+A_NUM: case A_NX+A_SI+A_NUM+A_FL: - if (((pflag & A_MI) == 0) && (d <= 0177)) *val = *val + (x << 8) + d; - else if ((pflag & A_MI) && (d <= 0200)) - *val = *val + (x << 8) + 0400 - d; +case A_PER: case A_PER+A_FL: /* . */ +case A_PER+A_SI+A_NUM: case A_PER+A_SI+A_NUM+A_FL: /* . + num */ +case A_PER+A_SI+A_MI+A_NUM: /* . - num */ +case A_PER+A_SI+A_MI+A_NUM+A_FL: +case A_NX+A_NUM: case A_NX+A_NUM+A_FL: /* num, ndx */ +case A_NX+A_SI+A_NUM: case A_NX+A_SI+A_NUM+A_FL: /* +num, ndx */ +case A_NX+A_SI+A_MI+A_NUM: /* -num, ndx */ +case A_NX+A_SI+A_MI+A_NUM+A_FL: + val[1] = x; /* set mode */ + if (((pflag & A_MI) == 0) && (d < dsign)) val[2] = d; + else if ((pflag & A_MI) && (d <= dsign)) val[2] = (dmax - d); else return NULL; break; default: return NULL; } /* end case */ return cptr; } + +/* Parse two registers + + Inputs: + *cptr = input string + term = second terminating character + val = output array + Outputs: + optr = pointer to next char in input string + NULL if error +*/ + +char *get_2reg (char *cptr, char term, int32 *val) +{ +char gbuf[CBUFSIZE]; +t_stat r; + +cptr = get_glyph (cptr, gbuf, ','); /* get register */ +val[0] = get_uint (gbuf, 8, I_M_SRC, &r); +if (r != SCPE_OK) return NULL; +cptr = get_glyph (cptr, gbuf, term); /* get register */ +val[1] = get_uint (gbuf, 8, I_M_DST, &r); +if (r != SCPE_OK) return NULL; +return cptr; +} /* Symbolic input @@ -592,8 +802,8 @@ return cptr; t_stat parse_sym (char *cptr, t_addr addr, UNIT *uptr, t_value *val, int32 sw) { -int32 cflag, d, i, j; -t_stat r; +int32 cflag, d, i, j, amd[3]; +t_stat r, rtn; char gbuf[CBUFSIZE]; cflag = (uptr == NULL) || (uptr == &cpu_unit); @@ -609,6 +819,7 @@ if ((sw & SWMASK ('C')) || ((*cptr == '"') && cptr++)) { /* ASCII string? */ /* Instruction parse */ +rtn = SCPE_OK; /* assume 1 word */ cptr = get_glyph (cptr, gbuf, 0); /* get opcode */ for (i = 0; (opcode[i] != NULL) && (strcmp (opcode[i], gbuf) != 0) ; i++) ; if (opcode[i] == NULL) return SCPE_ARG; @@ -638,24 +849,20 @@ case I_V_D: /* IOT dev */ if (r != SCPE_OK) return SCPE_ARG; val[0] = val[0] | (d << I_V_DEV); } break; -case I_V_RM: /* mem reg,addr */ +case I_V_RM: /* reg, addr */ cptr = get_glyph (cptr, gbuf, ','); /* get register */ d = get_uint (gbuf, 8, I_M_DST, &r); if (r != SCPE_OK) return SCPE_ARG; val[0] = val[0] | (d << I_V_DST); /* put in place */ -case I_V_M: - if ((cptr = get_addr (cptr, addr, cflag, &d)) == NULL) return SCPE_ARG; - val[0] = val[0] | d; +case I_V_M: /* addr */ + cptr = get_addr (cptr, addr, FALSE, cflag, amd); + if (cptr == NULL) return SCPE_ARG; + val[0] = val[0] | (amd[0] << I_V_IND) | (amd[1] << I_V_MODE) | amd[2]; break; case I_V_RR: /* operate */ - cptr = get_glyph (cptr, gbuf, ','); /* get register */ - d = get_uint (gbuf, 8, I_M_SRC, &r); - if (r != SCPE_OK) return SCPE_ARG; - val[0] = val[0] | (d << I_V_SRC); /* put in place */ - cptr = get_glyph (cptr, gbuf, ','); /* get register */ - d = get_uint (gbuf, 8, I_M_DST, &r); - if (r != SCPE_OK) return SCPE_ARG; - val[0] = val[0] | (d << I_V_DST); /* put in place */ + cptr = get_2reg (cptr, ',', amd); /* get 2 reg */ + if (cptr == NULL) return SCPE_ARG; + val[0] = val[0] | (amd[0] << I_V_SRC) | (amd[1] << I_V_DST); if (*cptr != 0) { /* skip? */ cptr = get_glyph (cptr, gbuf, 0); /* get skip */ for (i = 0; (skip[i] != NULL) && @@ -664,15 +871,80 @@ case I_V_RR: /* operate */ val[0] = val[0] | (i + 1); } /* end for */ break; case I_V_BY: /* byte */ - cptr = get_glyph (cptr, gbuf, ','); /* get register */ - d = get_uint (gbuf, 8, I_M_PULSE, &r); + cptr = get_2reg (cptr, 0, amd); /* get 2 reg */ + if (cptr == NULL) return SCPE_ARG; + val[0] = val[0] | (amd[0] << I_V_PULSE) | (amd[1] << I_V_DST); + break; +case I_V_2AC: /* reg, reg */ + cptr = get_2reg (cptr, 0, amd); /* get 2 reg */ + if (cptr == NULL) return SCPE_ARG; + val[0] = val[0] | (amd[0] << I_V_SRC) | (amd[1] << I_V_DST); + break; +case I_V_RSI: /* reg, short imm */ + cptr = get_glyph (cptr, gbuf, ','); /* get immediate */ + d = get_uint (gbuf, 8, I_M_SRC + 1, &r); + if ((d == 0) || (r != SCPE_OK)) return SCPE_ARG; + val[0] = val[0] | ((d - 1) << I_V_SRC); /* put in place */ + cptr = get_glyph (cptr, gbuf, 0); /* get register */ + d = get_uint (gbuf, 8, I_M_DST, &r); if (r != SCPE_OK) return SCPE_ARG; - val[0] = val[0] | (d << I_V_PULSE); /* put in place */ + val[0] = val[0] | (d << I_V_DST); /* put in place */ + break; +case I_V_RLI: /* reg, long imm */ + cptr = get_glyph (cptr, gbuf, ','); /* get immediate */ + val[1] = get_uint (gbuf, 8, DMASK, &r); + if (r != SCPE_OK) return SCPE_ARG; + cptr = get_glyph (cptr, gbuf, 0); /* get register */ + d = get_uint (gbuf, 8, I_M_DST, &r); + if (r != SCPE_OK) return SCPE_ARG; + val[0] = val[0] | (d << I_V_DST); /* put in place */ + rtn = -1; + break; +case I_V_LI: /* long imm */ + cptr = get_glyph (cptr, gbuf, 0); /* get immediate */ + val[1] = get_uint (gbuf, 8, DMASK, &r); + if (r != SCPE_OK) return SCPE_ARG; + rtn = -1; + break; +case I_V_RLM: /* reg, long mem */ cptr = get_glyph (cptr, gbuf, ','); /* get register */ d = get_uint (gbuf, 8, I_M_DST, &r); if (r != SCPE_OK) return SCPE_ARG; val[0] = val[0] | (d << I_V_DST); /* put in place */ +case I_V_LM: /* long mem */ + cptr = get_addr (cptr, addr, TRUE, cflag, amd); + if (cptr == NULL) return SCPE_ARG; + val[0] = val[0] | (amd[1] << I_V_MODE); + val[1] = (amd[0] << A_V_IND) | amd[2]; + rtn = -1; + break; +case I_V_FRM: /* flt reg, long mem */ + cptr = get_glyph (cptr, gbuf, ','); /* get register */ + d = get_uint (gbuf, 8, I_M_DST, &r); + if (r != SCPE_OK) return SCPE_ARG; + val[0] = val[0] | (d << I_V_DST); /* put in place */ + cptr = get_addr (cptr, addr, TRUE, cflag, amd); + if (cptr == NULL) return SCPE_ARG; + val[0] = val[0] | (amd[1] << I_V_SRC); + val[1] = (amd[0] << A_V_IND) | amd[2]; + rtn = -1; + break; +case I_V_FST: /* flt status */ + cptr = get_addr (cptr, addr, TRUE, cflag, amd); + if (cptr == NULL) return SCPE_ARG; + val[0] = val[0] | (amd[1] << I_V_DST); + val[1] = (amd[0] << A_V_IND) | amd[2]; + rtn = -1; + break; +case I_V_XP: /* XOP */ + cptr = get_2reg (cptr, ',', amd); /* get 2 reg */ + if (cptr == NULL) return SCPE_ARG; + val[0] = val[0] | (amd[0] << I_V_SRC) | (amd[1] << I_V_DST); + cptr = get_glyph (cptr, gbuf, 0); /* get argument */ + d = get_uint (gbuf, 8, I_M_XOP, &r); + if (r != SCPE_OK) return SCPE_ARG; + val[0] = val[0] | (d << I_V_XOP); break; } /* end case */ if (*cptr != 0) return SCPE_ARG; /* any leftovers? */ -return SCPE_OK; +return rtn; } diff --git a/nova_tt.c b/nova_tt.c index 5c16dfa1..20c56333 100644 --- a/nova_tt.c +++ b/nova_tt.c @@ -1,6 +1,6 @@ /* nova_tt.c: NOVA console terminal simulator - Copyright (c) 1993-1999, Robert M. Supnik + Copyright (c) 1993-2000, 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"), @@ -37,8 +37,6 @@ t_stat tto_svc (UNIT *uptr); t_stat tti_reset (DEVICE *dptr); t_stat tto_reset (DEVICE *dptr); t_stat ttx_setmod (UNIT *uptr, int32 value); -extern t_stat sim_activate (UNIT *uptr, int32 delay); -extern t_stat sim_cancel (UNIT *uptr); extern t_stat sim_poll_kbd (void); extern t_stat sim_putchar (int32 out); diff --git a/nova_tt1.c b/nova_tt1.c new file mode 100644 index 00000000..e5acc0af --- /dev/null +++ b/nova_tt1.c @@ -0,0 +1,245 @@ +/* nova_tt1.c: NOVA second terminal simulator + + Copyright (c) 1993-2000, Robert M. Supnik + Written by Bruce Ray and used with his gracious permission. + + 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 second terminal input + tto1 second terminal output +*/ + +#include "nova_defs.h" + +#define UNIT_V_DASHER (UNIT_V_UF + 0) /* Dasher mode */ +#define UNIT_DASHER (1 << UNIT_V_DASHER) + +extern int32 int_req, dev_busy, dev_done, dev_disable; +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); + +/* TTI1 data structures + + tti1_dev TTI1 device descriptor + tti1_unit TTI1 unit descriptor + tti1_reg TTI1 register list + ttx1_mod TTI1/TTO1 modifiers list +*/ + +UNIT tti1_unit = { UDATA (&tti1_svc, UNIT_SEQ+UNIT_ATTABLE, 0), KBD_POLL_WAIT }; + +REG tti1_reg[] = { + { ORDATA (BUF, tti1_unit.buf, 8) }, + { FLDATA (BUSY, dev_busy, INT_V_TTI1) }, + { FLDATA (DONE, dev_done, INT_V_TTI1) }, + { FLDATA (DISABLE, dev_disable, INT_V_TTI1) }, + { 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 }, + { NULL } }; + +MTAB ttx1_mod[] = { + { UNIT_DASHER, 0, "ANSI", "ANSI", &ttx1_setmod }, + { UNIT_DASHER, UNIT_DASHER, "Dasher", "DASHER", &ttx1_setmod }, + { 0 } }; + +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 }; + +/* TTO1 data structures + + tto1_dev TTO1 device descriptor + tto1_unit TTO1 unit descriptor + tto1_reg TTO1 register list +*/ + +UNIT tto1_unit = { UDATA (&tto1_svc, UNIT_SEQ+UNIT_ATTABLE, 0), SERIAL_OUT_WAIT }; + +REG tto1_reg[] = { + { ORDATA (BUF, tto1_unit.buf, 8) }, + { FLDATA (BUSY, dev_busy, INT_V_TTO1) }, + { FLDATA (DONE, dev_done, INT_V_TTO1) }, + { FLDATA (DISABLE, dev_disable, INT_V_TTO1) }, + { 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 }, + { NULL } }; + +DEVICE tto1_dev = { + "TTO1", &tto1_unit, tto1_reg, ttx1_mod, + 1, 10, 31, 1, 8, 8, + NULL, NULL, &tto1_reset, + NULL, NULL, NULL }; + +/* Terminal input: IOT routine */ + +int32 tti1 (int32 pulse, int32 code, int32 AC) +{ +int32 iodata; + +iodata = (code == ioDIA)? tti1_unit.buf & 0377: 0; +switch (pulse) { /* decode IR<8:9> */ +case iopS: /* start */ + dev_busy = dev_busy | INT_TTI1; /* set busy */ + dev_done = dev_done & ~INT_TTI1; /* clear done, int */ + int_req = int_req & ~INT_TTI1; + break; +case iopC: /* clear */ + dev_busy = dev_busy & ~INT_TTI1; /* clear busy */ + dev_done = dev_done & ~INT_TTI1; /* clear done, int */ + int_req = int_req & ~INT_TTI1; + break; } /* end switch */ +return iodata; +} + +/* Unit service */ + +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; } +tti1_unit.buf = temp & 0177; +if ((tti1_unit.flags & UNIT_DASHER) && (tti1_unit.buf == '\r')) + tti1_unit.buf = '\n'; /* Dasher: cr -> nl */ +dev_busy = dev_busy & ~INT_TTI1; /* clear busy */ +dev_done = dev_done | INT_TTI1; /* set done */ +int_req = (int_req & ~INT_DEV) | (dev_done & ~dev_disable); +tti1_unit.pos = tti1_unit.pos + 1; +return SCPE_OK; +} + +/* Reset routine */ + +t_stat tti1_reset (DEVICE *dptr) +{ +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? */ + 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 */ + +int32 tto1 (int32 pulse, int32 code, int32 AC) +{ +if (code == ioDOA) tto1_unit.buf = AC & 0377; +switch (pulse) { /* decode IR<8:9> */ +case iopS: /* start */ + dev_busy = dev_busy | INT_TTO1; /* set busy */ + dev_done = dev_done & ~INT_TTO1; /* clear done, int */ + int_req = int_req & ~INT_TTO1; + sim_activate (&tto1_unit, tto1_unit.wait); /* activate unit */ + break; +case iopC: /* clear */ + 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 */ + break; } /* end switch */ +return 0; +} + +/* Unit service */ + +t_stat tto1_svc (UNIT *uptr) +{ +int32 c ; + +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; } +tto1_unit.pos = tto1_unit.pos + 1; +return SCPE_OK; +} + +/* Reset routine */ + +t_stat tto1_reset (DEVICE *dptr) +{ +tto1_unit.buf = 0; +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 */ +return SCPE_OK; +} + +t_stat ttx1_setmod (UNIT *uptr, int32 value) +{ +tti1_unit.flags = (tti1_unit.flags & ~UNIT_DASHER) | value; +tto1_unit.flags = (tto1_unit.flags & ~UNIT_DASHER) | value; +return SCPE_OK; +} diff --git a/pdp11_cis.c b/pdp11_cis.c index 622fae8b..e978eb6a 100644 --- a/pdp11_cis.c +++ b/pdp11_cis.c @@ -1,6 +1,6 @@ /* pdp11_cis.c: PDP-11 CIS optional instruction set simulator - Copyright (c) 1993-1999, Robert M Supnik + Copyright (c) 1993-2000, 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"), diff --git a/pdp11_cpu.c b/pdp11_cpu.c index eab9ca8f..f0ec0122 100644 --- a/pdp11_cpu.c +++ b/pdp11_cpu.c @@ -1,6 +1,6 @@ /* pdp11_cpu.c: PDP-11 CPU simulator - Copyright (c) 1993-1999, Robert M Supnik + Copyright (c) 1993-2000, 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"), diff --git a/pdp11_defs.h b/pdp11_defs.h index fda91741..f2fba2a0 100644 --- a/pdp11_defs.h +++ b/pdp11_defs.h @@ -1,6 +1,6 @@ /* pdp11_defs.h: PDP-11 simulator definitions - Copyright (c) 1993-1999, Robert M Supnik + Copyright (c) 1993-2000, 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"), @@ -30,7 +30,7 @@ #include "sim_defs.h" /* simulator defns */ #include -/* Constants */ +/* Architectural constants */ #define STKLIM 0400 /* stack limit */ #define VASIZE 0200000 /* 2**16 */ @@ -168,15 +168,6 @@ typedef struct fpac fpac_t; #define CSR_BUSY (1u << CSR_V_BUSY) #define CSR_ERR (1u << CSR_V_ERR) -/* Simulator stop codes; codes 1:TRAP_V_MAX correspond to traps 0:TRAPMAX-1 */ - -#define STOP_HALT TRAP_V_MAX + 1 /* HALT instruction */ -#define STOP_IBKPT TRAP_V_MAX + 2 /* instruction bkpt */ -#define STOP_WAIT TRAP_V_MAX + 3 /* wait, no events */ -#define STOP_VECABORT TRAP_V_MAX + 4 /* abort vector read */ -#define STOP_SPABORT TRAP_V_MAX + 5 /* abort trap push */ -#define IORETURN(f,v) ((f)? (v): SCPE_OK) /* cond error return */ - /* Trap masks, descending priority order, following J-11 An interrupt summary bit is kept with traps, to minimize overhead */ @@ -231,6 +222,15 @@ typedef struct fpac fpac_t; #define VEC_PWRFL 0024 #define VEC_FPE 0244 +/* Simulator stop codes; codes 1:TRAP_V_MAX correspond to traps 0:TRAPMAX-1 */ + +#define STOP_HALT TRAP_V_MAX + 1 /* HALT instruction */ +#define STOP_IBKPT TRAP_V_MAX + 2 /* instruction bkpt */ +#define STOP_WAIT TRAP_V_MAX + 3 /* wait, no events */ +#define STOP_VECABORT TRAP_V_MAX + 4 /* abort vector read */ +#define STOP_SPABORT TRAP_V_MAX + 5 /* abort trap push */ +#define IORETURN(f,v) ((f)? (v): SCPE_OK) /* cond error return */ + /* Interrupt assignments, priority is right to left <3:0> = BR7, <3> = PIR7 diff --git a/pdp11_fp.c b/pdp11_fp.c index 044e9a38..536b2072 100644 --- a/pdp11_fp.c +++ b/pdp11_fp.c @@ -1,6 +1,6 @@ /* pdp11_fp.c: PDP-11 floating point simulator (32b version) - Copyright (c) 1993-1999, Robert M Supnik + Copyright (c) 1993-2000, 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"), diff --git a/pdp11_rk.c b/pdp11_rk.c index 2d5543bf..c97e3c5a 100644 --- a/pdp11_rk.c +++ b/pdp11_rk.c @@ -1,6 +1,6 @@ /* RK11 cartridge disk simulator - Copyright (c) 1993-1999, Robert M Supnik + Copyright (c) 1993-2000, 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"), diff --git a/pdp11_rl.c b/pdp11_rl.c index 7f30e412..8a1271d7 100644 --- a/pdp11_rl.c +++ b/pdp11_rl.c @@ -1,6 +1,6 @@ /* RL11 (RLV12) cartridge disk simulator - Copyright (c) 1993-1999, Robert M Supnik + Copyright (c) 1993-2000, 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"), diff --git a/pdp11_rp.c b/pdp11_rp.c index 9d5a35c5..327bb297 100644 --- a/pdp11_rp.c +++ b/pdp11_rp.c @@ -1,6 +1,6 @@ /* pdp11_rp.c - RP04/05/06/07 RM02/03/05/80 "Massbus style" disk controller - Copyright (c) 1993-1999, Robert M Supnik + Copyright (c) 1993-2000, 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"), diff --git a/pdp11_rx.c b/pdp11_rx.c index ba3f4511..10a46782 100644 --- a/pdp11_rx.c +++ b/pdp11_rx.c @@ -1,6 +1,6 @@ /* pdp11_rx.c: RX11/RX01 floppy disk simulator - Copyright (c) 1993-1999, Robert M Supnik + Copyright (c) 1993-2000, 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"), diff --git a/pdp11_tm.c b/pdp11_tm.c index 8e2a7aeb..2739c70b 100644 --- a/pdp11_tm.c +++ b/pdp11_tm.c @@ -1,6 +1,6 @@ /* PDP-11 magnetic tape simulator - Copyright (c) 1993-1999, Robert M Supnik + Copyright (c) 1993-2000, 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"), diff --git a/pdp18b_cpu.c b/pdp18b_cpu.c index 29b0c0b5..a7069f0c 100644 --- a/pdp18b_cpu.c +++ b/pdp18b_cpu.c @@ -1,6 +1,6 @@ /* pdp18b_cpu.c: 18b PDP CPU simulator - Copyright (c) 1993-1999, Robert M Supnik + Copyright (c) 1993-2000, 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,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. + 18-Dec-00 RMS Added PDP-9,-15 memm init register + 30-Nov-00 RMS Fixed numerous PDP-15 bugs 14-Apr-99 RMS Changed t_addr to unsigned The 18b PDP family has five distinct architectural variants: PDP-1, @@ -251,7 +253,12 @@ int32 int_req = 0; /* int requests */ int32 iors = 0; /* IORS */ int32 ion = 0; /* int on */ int32 ion_defer = 0; /* int defer */ -int32 memm = 0; /* ext mem mode */ +int32 memm = 0; /* mem mode */ +#if defined (PDP15) +int32 memm_init = 1; /* mem init */ +#else +int32 memm_init = 0; +#endif int32 usmd = 0; /* user mode */ int32 usmdbuf = 0; /* user mode buffer */ int32 trap_pending = 0; /* trap pending */ @@ -316,6 +323,7 @@ REG cpu_reg[] = { { FLDATA (PRVN, prvn, 0) }, { FLDATA (TRAPP, trap_pending, 0) }, { FLDATA (EXTM, memm, 0) }, + { FLDATA (EXTM_INIT, memm_init, 0) }, { FLDATA (EMIRP, emir_pending, 0) }, { FLDATA (RESTP, rest_pending, 0) }, { FLDATA (PWRFL, int_req, INT_V_PWRFL) }, @@ -329,6 +337,7 @@ REG cpu_reg[] = { { FLDATA (USMD, usmd, 0) }, { FLDATA (USMDBUF, usmdbuf, 0) }, { FLDATA (BANKM, memm, 0) }, + { FLDATA (BANKM_INIT, memm_init, 0) }, { FLDATA (RESP, rest_pending, 0) }, { FLDATA (PWRFL, int_req, INT_V_PWRFL) }, #endif @@ -344,8 +353,9 @@ MTAB cpu_mod[] = { #if !defined (PDP4) { UNIT_NOEAE, UNIT_NOEAE, "no EAE", "NOEAE", NULL }, { UNIT_NOEAE, 0, "EAE", "EAE", NULL }, -#endif +#else { UNIT_MSIZE, 4096, NULL, "4K", &cpu_set_size }, +#endif { UNIT_MSIZE, 8192, NULL, "8K", &cpu_set_size }, #if (MAXMEMSIZE > 8192) { UNIT_MSIZE, 12288, NULL, "12K", &cpu_set_size }, @@ -436,7 +446,8 @@ if (sim_interval <= 0) { /* check clock queue */ /* Protection traps work like interrupts, with these quirks: PDP-7 extend mode forced on, M[0] = PC, PC = 2 - PDP-9, PDP-15 extend/bank mode forced off, M[0/20] = PC, PC = 0/21 + 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) @@ -448,16 +459,23 @@ if (trap_pending) { /* trap pending? */ memm = 1; /* extend on */ emir_pending = trap_pending = 0; /* emir, trap off */ usmd = 0; } /* protect off */ -#endif - -#if defined (PDP9) || defined (PDP15) +#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 */ - memm = 0; /* extend/bank off */ emir_pending = rest_pending = trap_pending = 0; /* emir,rest,trap off */ usmd = 0; } /* protect off */ #endif @@ -467,7 +485,9 @@ if (ion && !ion_defer && int_req) { /* interrupt? */ M[0] = JMS_WORD (usmd); /* save state */ PC = 1; /* fetch next from 1 */ ion = 0; /* interrupts off */ - memm = 0; /* extend/bank off */ +#if !defined (PDP15) /* except PDP-15, */ + memm = 0; /* extend off */ +#endif emir_pending = rest_pending = 0; /* emir, restore off */ usmd = 0; } /* protect off */ @@ -559,9 +579,11 @@ if (PC == ibkpt_addr) { /* breakpoint? */ rest_pending = 0; \ LAC = ((M[MA] << 1) & 01000000) | (LAC & 0777777); \ memm = (M[MA] >> 16) & 1; \ - usmd = (M[MA] >> 15) & 1; } \ + usmd = (M[MA] >> 15) & 1; } \ MA = ((IR & damask & ~07) != 00010)? \ - (PC & BLKMASK) | (M[MA] & IAMASK): (M[MA] & ADDRMASK) + (PC & BLKMASK) | (M[MA] & IAMASK): (M[MA] & ADDRMASK); \ + damask = memm? 017777: 07777; \ + epcmask = ADDRMASK & ~damask #define CHECK_INDEX \ if ((IR & 0010000) && (memm == 0)) MA = (MA + XR) & ADDRMASK #define CHECK_ADDR_R(x) \ @@ -580,8 +602,9 @@ if (PC == ibkpt_addr) { /* breakpoint? */ /* Fetch, decode instruction */ -CHECK_ADDR_R (PC); /* validate PC */ -IR = M[PC]; /* fetch 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 (!ion_defer) usmd = usmdbuf; /* no IOT? load usmd */ @@ -591,7 +614,7 @@ xct_count = 0; /* track nested XCT's */ sim_interval = sim_interval - 1; xct_instr: /* label for XCT */ -MA = (PC & epcmask) | (IR & damask); /* effective address */ +MA = (MA & epcmask) | (IR & damask); /* effective address */ switch ((IR >> 13) & 037) { /* decode IR<0:4> */ /* LAC: opcode 20 */ @@ -767,7 +790,8 @@ case 031: /* JMP, indir */ CHECK_AUTO_INC; /* check auto inc */ #if defined (PDP7) || defined (PDP9) if (emir_pending && (((M[MA] >> 16) & 1) == 0)) memm = 0; -#elif defined (PDP9) +#endif +#if defined (PDP9) if (rest_pending) { /* restore pending? */ LAC = ((M[MA] << 1) & 01000000) | (LAC & 0777777); memm = (M[MA] >> 16) & 1; @@ -1069,14 +1093,18 @@ case 035: /* index operates */ #if defined (PDP15) t = (IR & 0400)? IR | 0777000: IR & 0377; /* sext immediate */ switch ((IR >> 9) & 017) { /* case on IR<5:8> */ + case 000: /* AAS */ + LAC = (LAC & 01000000) | ((LAC + t) & 0777777); + if (SEXT (LAC & 0777777) >= SEXT (LR)) + PC = INCR_ADDR (PC); case 001: /* PAX */ XR = LAC & 0777777; break; case 002: /* PAL */ LR = LAC & 0777777; break; - case 003: - LAC = (LAC & 01000000) | ((LAC + t) & 0777777); /* AAC */ + case 003: /* AAC */ + LAC = (LAC & 01000000) | ((LAC + t) & 0777777); break; case 004: /* PXA */ LAC = (LAC & 01000000) | XR; @@ -1094,10 +1122,13 @@ case 035: /* index operates */ case 011: /* PLX */ XR = LR; break; + case 014: /* CLAC */ + LAC = LAC & 01000000; + break; case 015: /* CLX */ XR = 0; break; - case 016: /* CLL */ + case 016: /* CLLR */ LR = 0; break; case 017: /* AXR */ @@ -1251,6 +1282,8 @@ case 034: /* IOT */ else if (pulse == 042) rest_pending = 1; /* RES */ else if (pulse == 062) memm = 0; /* DBA */ else if (pulse == 064) memm = 1; /* EBA */ + damask = memm? 017777: 07777; /* set dir addr mask */ + epcmask = ADDRMASK & ~damask; /* extended PC mask */ break; #endif @@ -1335,7 +1368,8 @@ eae_ac_sign = 0; ion = ion_defer = 0; int_req = int_req & ~INT_PWRFL; BR = 0; -memm = usmd = usmdbuf = 0; +usmd = usmdbuf = 0; +memm = memm_init; nexm = prvn = trap_pending = 0; emir_pending = rest_pending = 0; return cpu_svc (&cpu_unit); diff --git a/pdp18b_defs.h b/pdp18b_defs.h index 44dd219b..2fe52b3c 100644 --- a/pdp18b_defs.h +++ b/pdp18b_defs.h @@ -1,6 +1,6 @@ /* pdp18b_defs.h: 18b PDP simulator definitions - Copyright (c) 1993-1999, Robert M Supnik + Copyright (c) 1993-2000, 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"), @@ -29,7 +29,8 @@ 19-Mar-95 RMS Added dynamic memory size The author gratefully acknowledges the help of Craig St. Clair and - Deb Tevonian in locating archival material about the 18b PDP's + Deb Tevonian in locating archival material about the 18b PDP's, and of + Al Kossow and Max Burnet in making documentation and software available. */ #include "sim_defs.h" /* simulator defns */ @@ -74,7 +75,14 @@ #define PDP9 0 /* default to PDP-9 */ #endif -/* Memory and peripheral configuration */ +/* Simulator stop codes */ + +#define STOP_RSRV 1 /* must be 1 */ +#define STOP_HALT 2 /* HALT */ +#define STOP_IBKPT 3 /* breakpoint */ +#define STOP_XCT 4 /* nested XCT's */ + +/* Peripheral configuration */ #if defined (PDP4) #define ADDRSIZE 13 @@ -95,21 +103,23 @@ #define RF 0 /* fixed head disk */ #define RP 0 /* disk pack */ #define MTA 0 /* magtape */ -#define BLKMASK 0300000 /* block mask */ #endif +/* Memory */ + #define ADDRMASK ((1 << ADDRSIZE) - 1) /* address mask */ #define IAMASK 077777 /* ind address mask */ +#define BLKMASK (ADDRMASK & (~IAMASK)) /* block mask */ #define MAXMEMSIZE (1 << ADDRSIZE) /* max memory size */ #define MEMSIZE (cpu_unit.capac) /* actual memory size */ #define MEM_ADDR_OK(x) (((t_addr) (x)) < MEMSIZE) -/* Simulator stop codes */ +/* Architectural constants */ -#define STOP_RSRV 1 /* must be 1 */ -#define STOP_HALT 2 /* HALT */ -#define STOP_IBKPT 3 /* breakpoint */ -#define STOP_XCT 4 /* nested XCT's */ +#define DMASK 0777777 /* data mask */ +#define LINK (DMASK + 1) /* link */ +#define LACMASK (LINK | DMASK) /* link + data */ +#define SIGN 0400000 /* sign bit */ /* IOT subroutine return codes */ diff --git a/pdp18b_drm.c b/pdp18b_drm.c index a2126121..a4a17d58 100644 --- a/pdp18b_drm.c +++ b/pdp18b_drm.c @@ -1,6 +1,6 @@ /* pdp18b_drm.c: drum/fixed head disk simulator - Copyright (c) 1993-1999, Robert M Supnik + Copyright (c) 1993-2000, 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"), diff --git a/pdp18b_lp.c b/pdp18b_lp.c index 414ea98f..6f73fb63 100644 --- a/pdp18b_lp.c +++ b/pdp18b_lp.c @@ -399,8 +399,6 @@ char lpt_buf[LPT_BSIZE] = { 0 }; t_stat lpt_svc (UNIT *uptr); t_stat lpt_reset (DEVICE *dptr); -t_stat lpt_attach (UNIT *uptr, char *cptr); -t_stat lpt_detach (UNIT *uptr); int32 lpt_updsta (int32 new); extern t_stat sim_activate (UNIT *uptr, int32 delay); extern t_stat sim_cancel (UNIT *uptr); @@ -434,7 +432,7 @@ DEVICE lpt_dev = { "LPT", &lpt_unit, lpt_reg, NULL, 1, 10, 31, 1, 8, 8, NULL, NULL, &lpt_reset, - NULL, &lpt_attach, &lpt_detach }; + NULL, NULL, NULL }; /* LP15 line printer: IOT routines */ @@ -463,7 +461,7 @@ return AC; int32 lpt66 (int32 pulse, int32 AC) { if (pulse == 021) lpt_sta = lpt_sta & ~STA_DON; /* LPCD */ -if (pulse == 041) lpt_sta = lpt_sta & STA_ALM; /* LPCF */ +if (pulse == 041) lpt_sta = lpt_sta = 0; /* LPCF */ lpt_updsta (0); /* update status */ return AC; } @@ -540,8 +538,7 @@ t_stat lpt_reset (DEVICE *dptr) { mode = lcnt = bptr = 0; /* clear controls */ sim_cancel (&lpt_unit); /* deactivate unit */ -if (lpt_unit.flags & UNIT_ATT) lpt_sta = 0; -else lpt_sta = STA_ALM; +lpt_sta = 0; /* clear status */ lpt_ie = 1; /* enable interrupts */ lpt_updsta (0); /* update status */ return SCPE_OK; @@ -554,23 +551,4 @@ int32 lpt_iors (void) return ((lpt_sta & STA_DON)? IOS_LPT: 0); } -/* Attach routine */ - -t_stat lpt_attach (UNIT *uptr, char *cptr) -{ -t_stat reason; - -reason = attach_unit (uptr, cptr); -if (lpt_unit.flags & UNIT_ATT) lpt_sta = lpt_sta & ~STA_ALM; -lpt_updsta (0); -return reason; -} - -/* Detach routine */ - -t_stat lpt_detach (UNIT *uptr) -{ -lpt_updsta (STA_ALM); -return detach_unit (uptr); -} #endif diff --git a/pdp18b_mt.c b/pdp18b_mt.c index 50a02ebf..59947832 100644 --- a/pdp18b_mt.c +++ b/pdp18b_mt.c @@ -1,6 +1,6 @@ /* 18b PDP magnetic tape simulator - Copyright (c) 1993-1999, Robert M Supnik + Copyright (c) 1993-2000, 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"), diff --git a/pdp18b_rf.c b/pdp18b_rf.c index 5362aaca..86d863b8 100644 --- a/pdp18b_rf.c +++ b/pdp18b_rf.c @@ -1,6 +1,6 @@ /* pdp18b_rf.c: fixed head disk simulator - Copyright (c) 1993-1999, Robert M Supnik + Copyright (c) 1993-2000, 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"), @@ -26,6 +26,7 @@ rf RF09/RF09 for PDP-9 RF15/RS09 for PDP-15 + 30-Nov-99 RMS Added non-zero requirement to rf_time 14-Apr-99 RMS Changed t_addr to unsigned The RFxx is a head-per-track disk. It uses the multicycle data break @@ -33,7 +34,7 @@ Two timing parameters are provided: - rf_time Interword timing. If 0, treated as 1. + rf_time Interword timing. Must be non-zero. rf_burst Burst mode. If 0, DMA occurs cycle by cycle; otherwise, DMA occurs in a burst. */ @@ -76,9 +77,8 @@ #define RFS_CLR 0000170 /* always clear */ #define RFS_EFLGS (RFS_HDW | RFS_APE | RFS_MXF | RFS_WCE | \ RFS_DPE | RFS_WLO | RFS_NED ) /* error flags */ -#define MIN_TIME(x) ((x > 0)? (x): 1) #define GET_FNC(x) (((x) >> RFS_V_FNC) & RFS_M_FNC) -#define GET_POS(x) ((int) fmod (sim_gtime() / ((double) (MIN_TIME(x))), \ +#define GET_POS(x) ((int) fmod (sim_gtime() / ((double) (x)), \ ((double) RF_NUMWD))) #define RF_BUSY (sim_is_active (&rf_unit)) @@ -125,7 +125,7 @@ REG rf_reg[] = { { ORDATA (WLK5, rf_wlk[5], 16) }, { ORDATA (WLK6, rf_wlk[6], 16) }, { ORDATA (WLK7, rf_wlk[7], 16) }, - { DRDATA (TIME, rf_time, 24), PV_LEFT }, + { DRDATA (TIME, rf_time, 24), PV_LEFT + REG_NZ }, { FLDATA (BURST, rf_burst, 0) }, { FLDATA (STOP_IOE, rf_stopioe, 0) }, { NULL } }; @@ -232,7 +232,7 @@ do { pa = M[RF_MA] = (M[RF_MA] + 1) & ADDRMASK; /* incr mem addr */ while ((M[RF_WC] != 0) && (rf_burst != 0)); /* brk if wc, no brst */ if ((M[RF_WC] != 0) && ((rf_sta & RFS_ERR) == 0)) /* more to do? */ - sim_activate (&rf_unit, MIN_TIME (rf_time)); /* sched next */ + sim_activate (&rf_unit, rf_time); /* sched next */ else rf_updsta (RFS_DON); return SCPE_OK; } diff --git a/pdp18b_rp.c b/pdp18b_rp.c index 56a67656..24b3b566 100644 --- a/pdp18b_rp.c +++ b/pdp18b_rp.c @@ -1,6 +1,6 @@ /* RP15/RP02 disk pack simulator - Copyright (c) 1993-1999, Robert M Supnik + Copyright (c) 1993-2000, 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"), diff --git a/pdp18b_stddev.c b/pdp18b_stddev.c index e47a7804..0e39e647 100644 --- a/pdp18b_stddev.c +++ b/pdp18b_stddev.c @@ -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. + 22-Dec-00 RMS Added PDP-9/15 half duplex support + 30-Nov-00 RMS Fixed PDP-4/7 bootstrap loader for 4K systems 30-Oct-00 RMS Standardized register naming 06-Jan-97 RMS Fixed PDP-4 console input 16-Dec-96 RMS Fixed bug in binary ptr service @@ -39,6 +41,7 @@ extern int32 int_req, saved_PC; extern int32 M[]; +extern UNIT cpu_unit; int32 clk_state = 0; int32 ptr_err = 0, ptr_stopioe = 0, ptr_state = 0; int32 ptp_err = 0, ptp_stopioe = 0; @@ -184,8 +187,14 @@ static const int32 tti_trans[128] = { #define TTI_MASK ((1 << TTI_WIDTH) - 1) #define UNIT_V_UC (UNIT_V_UF + 0) /* UC only */ #define UNIT_UC (1 << UNIT_V_UC) +#define UNIT_V_HDX (UNIT_V_UF + 1) /* half duplex */ +#define UNIT_HDX (1 << UNIT_V_HDX) +#if defined (PDP4) || defined (PDP7) UNIT tti_unit = { UDATA (&tti_svc, UNIT_UC, 0), KBD_POLL_WAIT }; +#else +UNIT tti_unit = { UDATA (&tti_svc, UNIT_UC + UNIT_HDX, 0), KBD_POLL_WAIT }; +#endif REG tti_reg[] = { { ORDATA (BUF, tti_unit.buf, TTI_WIDTH) }, @@ -195,6 +204,7 @@ REG tti_reg[] = { { ORDATA (TTI_STATE, tti_state, (TTI_WIDTH + 3)), REG_HRO }, #else { FLDATA (UC, tti_unit.flags, UNIT_V_UC), REG_HRO }, + { FLDATA (HDX, tti_unit.flags, UNIT_V_HDX), REG_HRO }, #endif { DRDATA (POS, tti_unit.pos, 31), PV_LEFT }, { DRDATA (TIME, tti_unit.wait, 24), REG_NZ + PV_LEFT }, @@ -204,6 +214,8 @@ MTAB tti_mod[] = { #if !defined (KSR28) { UNIT_UC, 0, "lower case", "LC", NULL }, { UNIT_UC, UNIT_UC, "upper case", "UC", NULL }, + { UNIT_HDX, 0, "full duplex", "FDX", NULL }, + { UNIT_HDX, UNIT_HDX, "half duplex", "HDX", NULL }, #endif { 0 } }; @@ -392,7 +404,15 @@ ptr_err = 1; return detach_unit (uptr); } -/* Bootstrap routine */ +#if defined (PDP4) || defined (PDP7) + +/* Bootstrap routine, PDP-4 and PDP-7 + + In a 4K system, the boostrap resides at 7762-7776. + In an 8K or greater system, the bootstrap resides at 17762-17776. + Because the program is so small, simple masking can be + used to remove addr<5> for a 4K system. + */ #define BOOT_START 017762 #define BOOT_PC 017770 @@ -416,12 +436,26 @@ static const int32 boot_rom[] = { t_stat ptr_boot (int32 unitno) { -int32 i; +int32 i, mask; -for (i = 0; i < BOOT_LEN; i++) M[BOOT_START + i] = boot_rom[i]; -saved_PC = BOOT_PC; +if (MEMSIZE < 8192) mask = 0767777; /* 4k? */ +else mask = 0777777; +for (i = 0; i < BOOT_LEN; i++) + M[(BOOT_START & mask) + i] = boot_rom[i] & mask; +saved_PC = BOOT_PC & mask; return SCPE_OK; } + +#else + +/* PDP-9 and PDP-15 have built-in hardware RIM loaders */ + +t_stat ptr_boot (int32 unitno) +{ +return SCPE_ARG; +} + +#endif /* Paper tape punch: IOT routine */ @@ -519,6 +553,7 @@ 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); tti_unit.buf = temp | 0200; /* got char */ #endif int_req = int_req | INT_TTI; /* set flag */ diff --git a/pdp18b_sys.c b/pdp18b_sys.c index 35aa2de6..e96012a1 100644 --- a/pdp18b_sys.c +++ b/pdp18b_sys.c @@ -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. + 30-Nov-00 RMS Added PDP-9,-15 RIM/BIN loader format 30-Oct-00 RMS Added support for examine to file 27-Oct-98 RMS V2.4 load interface 20-Oct-97 RMS Fixed endian dependence in RIM loader @@ -103,41 +104,125 @@ const char *sim_stop_messages[] = { "Breakpoint", "Nested XCT's" }; -/* Binary loader +/* Binary loader */ - Until someone finds the binary loader documentation, - this implements RIM loader format -*/ - -int32 getword (FILE *fileref) +int32 getword (FILE *fileref, int32 *hi) { -int32 i, tmp, word; +int32 word, bits, st, ch; -word = 0; -for (i = 0; i < 3;) { - if ((tmp = getc (fileref)) == EOF) return -1; - if (tmp & 0200) { - word = (word << 6) | (tmp & 077); - i++; } } +word = st = bits = 0; +do { if ((ch = getc (fileref)) == EOF) return -1; + if (ch & 0200) { + word = (word << 6) | (ch & 077); + bits = (bits << 1) | ((ch >> 6) & 1); + st++; } } +while (st < 3); +if (hi != NULL) *hi = bits; return word; } +#if defined (PDP4) || defined (PDP7) + +/* PDP-4/PDP-7: RIM format only + + Tape format + dac addr + data + : + dac addr + data + jmp addr or hlt +*/ + t_stat sim_load (FILE *fileref, char *cptr, int flag) { int32 origin, val; if ((*cptr != 0) || (flag != 0)) return SCPE_ARG; for (;;) { - if ((val = getword (fileref)) < 0) return SCPE_FMT; - if ((val & 0760000) == 0040000) { /* DAC? */ + if ((val = getword (fileref, NULL)) < 0) return SCPE_FMT; + if ((val & 0760000) == 0040000) { /* DAC? */ origin = val & 017777; - if ((val = getword (fileref)) < 0) return SCPE_FMT; + if ((val = getword (fileref, NULL)) < 0) return SCPE_FMT; if (MEM_ADDR_OK (origin)) M[origin++] = val; } - else if ((val & 0760000) == 0600000) { + else if ((val & 0760000) == 0600000) { /* JMP? */ saved_PC = val & 017777; - return SCPE_OK; } } + return SCPE_OK; } + else if (val == 0740040) return SCPE_OK; /* HLT? */ + else return SCPE_FMT; } /* error */ return SCPE_FMT; /* error */ } + +#else + +/* PDP-9/PDP-15: RIM format and BIN format + + RIM format (read in address specified externally) + data + : + data + word to execute (bit 1 of last character set) + + BIN format (starts after RIM bootstrap) + block/ origin (>= 0) + count + checksum + data + : + data + block/ + : + endblock/ origin (< 0) +*/ + +t_stat sim_load (FILE *fileref, char *cptr, int flag) +{ +extern int32 sim_switches; +int32 i, bits, origin, count, cksum, val; +t_stat r; +char gbuf[CBUFSIZE]; + +/* RIM loader */ + +if (sim_switches & SWMASK ('R')) { /* RIM load? */ + if (*cptr != 0) { /* more input? */ + cptr = get_glyph (cptr, gbuf, 0); /* get origin */ + origin = get_uint (gbuf, 8, ADDRMASK, &r); + if (r != SCPE_OK) return r; + if (*cptr != 0) return SCPE_ARG; } /* no more */ + else origin = 0200; /* default 200 */ + + for (bits = 0; (bits & 1) == 0; ) { /* word loop */ + if ((val = getword (fileref, &bits)) < 0) return SCPE_FMT; + saved_PC = origin & ADDRMASK; /* save start */ + if (MEM_ADDR_OK (origin)) M[origin++] = val; } /* store word */ + return SCPE_OK; } /* found word + +/* Binary loader */ + +if (*cptr != 0) return SCPE_ARG; /* no arguments */ +do { val = getc (fileref); } /* find end RIM */ +while (((val & 0100) == 0) && (val != EOF)); +if (val == EOF) rewind (fileref); /* no RIM? rewind */ +for (;;) { /* block loop */ + if ((val = getword (fileref, NULL)) < 0) return SCPE_FMT; + if (val & SIGN) { + if (val != DMASK) saved_PC = val & 077777; + return SCPE_OK; } + cksum = origin = val; /* save origin */ + if ((val = getword (fileref, NULL)) < 0) return SCPE_FMT; + cksum = cksum + val; /* add to cksum */ + count = (-val) & DMASK; /* save count */ + if ((val = getword (fileref, NULL)) < 0) return SCPE_FMT; + cksum = cksum + val; /* add to cksum */ + for (i = 0; i < count; i++) { + if ((val = getword (fileref, NULL)) < 0) return SCPE_FMT; + cksum = cksum + val; + if (MEM_ADDR_OK (origin)) M[origin++] = val; } + if ((cksum & DMASK) != 0) return SCPE_CSUM; } +return SCPE_FMT; +} +#endif /* Symbol tables */ @@ -169,7 +254,7 @@ return SCPE_FMT; /* error */ #define MD(x) ((I_EMD) + ((x) << I_V_DC)) static const int32 masks[] = { - 0777777, 0777767, 0740000, 0740000, + 0777777, 0777767, 0740000, 0760000, 0763730, 0760000, 0777000, 0777000, 0740700, 0760700, 0777700 }; @@ -177,7 +262,21 @@ static const char *opcode[] = { "CAL", "DAC", "JMS", "DZM", /* mem refs */ "LAC", "XOR", "ADD", "TAD", "XCT", "ISZ", "AND", "SAD", - "JMP", "LAW", + "JMP", + +#if defined (PDP15) /* mem ref ind */ + "CAL*", "DAC*", "JMS*", "DZM*", /* normal */ + "LAC*", "XOR*", "ADD*", "TAD*", + "XCT*", "ISZ*", "AND*", "SAD*", + "JMP*", +#else + "CAL I", "DAC I", "JMS I", "DZM I", /* decode only */ + "LAC I", "XOR I", "ADD I", "TAD I", + "XCT I", "ISZ I", "AND I", "SAD I", + "JMP I", +#endif + + "LAW", /* LAW */ "LACQ", "LACS", "ABS", "GSM", "LMQ", /* EAE */ "MUL", "MULS", "DIV", "DIVS", @@ -243,10 +342,11 @@ static const char *opcode[] = { "LPDI", "LPEI", #elif defined (PDP15) "PFSF", "TTS", "SPCO", "CAF", - "DBR", "SKP15", "SBA", "DBA", "EBA", - "PAX", "PAL", "AAC", "PXA", - "AXS", "PXL", "PLA", "PLX", - "CLX", "CLL", "AXR", + "DBR", "SKP15", "RES", + "SBA", "DBA", "EBA", + "AAS", "PAX", "PAL", "AAC", + "PXA", "AXS", "PXL", "PLA", + "PLX", "CLAC","CLX", "CLLR", "AXR", #endif "IOT", /* general */ @@ -309,7 +409,13 @@ static const int32 opc_val[] = { 0000000+I_MRF, 0040000+I_MRF, 0100000+I_MRF, 0140000+I_MRF, 0200000+I_MRF, 0240000+I_MRF, 0300000+I_MRF, 0340000+I_MRF, 0400000+I_MRF, 0440000+I_MRF, 0500000+I_MRF, 0540000+I_MRF, - 0600000+I_MRF, 0760000+I_LAW, + 0600000+I_MRF, + 0020000+I_MRF, 0060000+I_MRF, 0120000+I_MRF, 0160000+I_MRF, + 0220000+I_MRF, 0260000+I_MRF, 0320000+I_MRF, 0360000+I_MRF, + 0420000+I_MRF, 0460000+I_MRF, 0520000+I_MRF, 0560000+I_MRF, + 0620000+I_MRF, + + 0760000+I_LAW, 0641002+I_NPN, 0641001+I_NPN, 0644000+I_NPN, 0664000+I_NPN, 0652000+I_NPN, 0653100+MD(022), 0657100+MD(022), 0640300+MD(023), 0644300+MD(023), @@ -375,10 +481,11 @@ static const int32 opc_val[] = { 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, 0707761+I_NPI, 0707762+I_NPI, 0707764+I_NPI, - 0721000+I_XR, 0722000+I_XR, 0723000+I_XR9, 0724000+I_XR, - 0725000+I_XR9, 0726000+I_XR, 0730000+I_XR, 0731000+I_XR, - 0735000+I_XR, 0736000+I_XR, 0737000+I_XR9, + 0703344+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 0700000+I_IOT, @@ -515,21 +622,13 @@ for (i = 0; opc_val[i] >= 0; i++) { /* loop thru ops */ ma = (addr & 0760000) | disp; } else { disp = inst & 007777; ma = (addr & 0770000) | disp; } -#else - disp = inst & 017777; - ma = (addr & 0760000) | disp; -#endif -#if defined (PDP9) || (PDP15) - if ((disp & ~07) == 00010) ma = ma & 00017; -#endif -#if defined (PDP15) - fprintf (of, "%s%s%-o", opcode[i], - ((inst & 0020000)? " @": " "), + fprintf (of, "%s %-o", opcode[i], (cflag? ma & ADDRMASK: disp)); if (!memm && (inst & 0010000)) fprintf (of, ",X"); #else - fprintf (of, "%s%s%-o", opcode[i], - ((inst & 0020000)? " I ": " "), + disp = inst & 017777; + ma = (addr & 0760000) | disp; + fprintf (of, "%s %-o", opcode[i], (cflag? ma & ADDRMASK: disp)); #endif break; @@ -635,7 +734,7 @@ if ((sw & SWMASK ('P')) || ((*cptr == '#') && cptr++)) { /* packed string? */ cptr = get_glyph (cptr, gbuf, 0); /* get opcode */ for (i = 0; (opcode[i] != NULL) && (strcmp (opcode[i], gbuf) != 0) ; i++) ; if (opcode[i] == NULL) return SCPE_ARG; -val[0] = opc_val[i] & 0777777; /* get value */ +val[0] = opc_val[i] & DMASK; /* get value */ j = (opc_val[i] >> I_V_FL) & I_M_FL; /* get class */ switch (j) { /* case on class */ @@ -656,33 +755,30 @@ case I_V_LAW: /* law */ val[0] = val[0] | d; break; case I_V_MRF: /* mem ref */ -#if !defined (PDP15) +#if defined (PDP15) + if (memm) dmask = 017777; + else dmask = 07777; + cptr = get_glyph (cptr, gbuf, ','); /* get glyph */ +#else dmask = 017777; cptr = get_glyph (cptr, gbuf, 0); /* get next field */ if (strcmp (gbuf, "I") == 0) { /* indirect? */ val[0] = val[0] | 020000; cptr = get_glyph (cptr, gbuf, 0); } -#else - if (memm) dmask = 017777; - else dmask = 07777; - if (*cptr == '@') { /* indirect? */ - val[0] = val[0] | 020000; - cptr++; } - cptr = get_glyph (cptr, gbuf, ','); /* get glyph */ #endif - epcmask = ADDRMASK & ~dmask; - d = get_uint (gbuf, 8, ADDRMASK, &r); + epcmask = ADDRMASK & ~dmask; /* get ePC */ + d = get_uint (gbuf, 8, ADDRMASK, &r); /* get addr */ if (r != SCPE_OK) return SCPE_ARG; - if (d <= dmask) val[0] = val[0] | d; + if (d <= dmask) val[0] = val[0] | d; /* fit in 12/13b? */ else if (cflag && (((addr ^ d) & epcmask) == 0)) - val[0] = val[0] | (d & dmask); + val[0] = val[0] | (d & dmask); /* hi bits = ePC? */ else return SCPE_ARG; #if defined (PDP15) if (!memm) { cptr = get_glyph (cptr, gbuf, 0); if (gbuf[0] != 0) { if (strcmp (gbuf, "X") != 0) return SCPE_ARG; - val[0] = val[0] + 010000; } } + val[0] = val[0] | 010000; } } #endif break; case I_V_EMD: /* or'able */ @@ -694,7 +790,7 @@ case I_V_NPN: case I_V_NPI: case I_V_IOT: case I_V_OPR: for (i = 0; (opcode[i] != NULL) && (strcmp (opcode[i], gbuf) != 0) ; i++) ; if (opcode[i] != NULL) { - k = opc_val[i] & 0777777; + k = opc_val[i] & DMASK; if (((k ^ val[0]) & 0740000) != 0) return SCPE_ARG; val[0] = val[0] | k; } else { d = get_sint (gbuf, & sign, &r); diff --git a/pdp1_cpu.c b/pdp1_cpu.c index a0bd9801..832f4fe2 100644 --- a/pdp1_cpu.c +++ b/pdp1_cpu.c @@ -1,6 +1,6 @@ /* pdp1_cpu.c: PDP-1 CPU simulator - Copyright (c) 1993-1999, Robert M. Supnik + Copyright (c) 1993-2000, 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,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. + 16-Dec-00 RMS Fixed bug in XCT address calculation 14-Apr-99 RMS Changed t_addr to unsigned The PDP-1 was Digital's first computer. Although Digital built four @@ -206,7 +207,7 @@ #include "pdp1_defs.h" -#define ILL_ADR_FLAG (1 << ADDRSIZE) +#define ILL_ADR_FLAG (1 << ASIZE) #define save_ibkpt (cpu_unit.u3) #define UNIT_V_MDV (UNIT_V_UF) /* mul/div */ #define UNIT_MDV (1 << UNIT_V_MDV) @@ -232,7 +233,7 @@ int32 stop_inst = 0; /* stop on rsrv inst */ int32 xct_max = 16; /* nested XCT limit */ int32 ind_max = 16; /* nested ind limit */ int32 old_PC = 0; /* old PC */ -int32 ibkpt_addr = ILL_ADR_FLAG | ADDRMASK; /* breakpoint addr */ +int32 ibkpt_addr = ILL_ADR_FLAG | AMASK; /* breakpoint addr */ t_stat cpu_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw); t_stat cpu_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw); @@ -294,7 +295,7 @@ int32 sc_map[512] = { UNIT cpu_unit = { UDATA (&cpu_svc, UNIT_FIX + UNIT_BINK, MAXMEMSIZE) }; REG cpu_reg[] = { - { ORDATA (PC, PC, ADDRSIZE) }, + { ORDATA (PC, PC, ASIZE) }, { ORDATA (AC, AC, 18) }, { ORDATA (IO, IO, 18) }, { FLDATA (OV, OV, 0) }, @@ -308,14 +309,14 @@ REG cpu_reg[] = { { FLDATA (SBIP, sbs, SB_V_IP) }, { FLDATA (IOH, ioh, 0) }, { FLDATA (IOC, ioc, 0) }, - { ORDATA (OLDPC, old_PC, ADDRSIZE), REG_RO }, + { ORDATA (OLDPC, old_PC, ASIZE), REG_RO }, { FLDATA (STOP_INST, stop_inst, 0) }, { FLDATA (SBS_INIT, sbs_init, SB_V_ON) }, { FLDATA (EXTM_INIT, extm_init, 0) }, { FLDATA (MDV, cpu_unit.flags, UNIT_V_MDV), REG_HRO }, { DRDATA (XCT_MAX, xct_max, 8), PV_LEFT + REG_NZ }, { DRDATA (IND_MAX, ind_max, 8), PV_LEFT + REG_NZ }, - { ORDATA (BREAK, ibkpt_addr, ADDRSIZE + 1) }, + { ORDATA (BREAK, ibkpt_addr, ASIZE + 1) }, { ORDATA (WRU, sim_int_char, 8) }, { NULL } }; @@ -336,7 +337,7 @@ MTAB cpu_mod[] = { DEVICE cpu_dev = { "CPU", &cpu_unit, cpu_reg, cpu_mod, - 1, 8, ADDRSIZE, 1, 8, 18, + 1, 8, ASIZE, 1, 8, 18, &cpu_ex, &cpu_dep, &cpu_reset, NULL, NULL, NULL }; @@ -382,28 +383,29 @@ if (PC == ibkpt_addr) { /* breakpoint? */ /* Fetch, decode instruction */ -IR = M[PC]; /* fetch instruction */ +MA = PC; /* PC to MA */ +IR = M[MA]; /* fetch instruction */ PC = INCR_ADDR (PC); /* increment PC */ xct_count = 0; /* track nested XCT's */ sim_interval = sim_interval - 1; xct_instr: /* label for XCT */ -if ((IR == 0610001) && ((PC & EPCMASK) == 0) && (sbs & SB_ON)) { +if ((IR == 0610001) && ((MA & EPCMASK) == 0) && (sbs & SB_ON)) { sbs = sbs & ~SB_IP; /* seq debreak */ old_PC = PC; /* save old PC */ OV = (M[1] >> 17) & 1; /* restore OV */ extm = (M[1] >> 16) & 1; /* restore ext mode */ - PC = M[1] & ADDRMASK; /* JMP I 1 */ + PC = M[1] & AMASK; /* JMP I 1 */ continue; } op = ((IR >> 13) & 037); /* get opcode */ if ((op < 032) && (op != 007)) { /* mem ref instr */ - MA = (PC & EPCMASK) | (IR & DAMASK); /* effective address */ + MA = (MA & EPCMASK) | (IR & DAMASK); /* direct address */ if (IR & IA) { /* indirect addr? */ - if (extm) MA = M[MA] & ADDRMASK; /* if ext, one level */ + if (extm) MA = M[MA] & AMASK; /* if ext, one level */ else { for (i = 0; i < ind_max; i++) { /* count indirects */ t = M[MA]; /* get indirect word */ - MA = (PC & EPCMASK) | (t & DAMASK); + MA = (MA & EPCMASK) | (t & DAMASK); if ((t & IA) == 0) break; } if (i >= ind_max) { /* indirect loop? */ reason = STOP_IND; diff --git a/pdp1_defs.h b/pdp1_defs.h index 89032d04..79d2e2a8 100644 --- a/pdp1_defs.h +++ b/pdp1_defs.h @@ -38,20 +38,6 @@ #include "sim_defs.h" -/* Memory and peripheral configuration */ - -#define ADDRSIZE 16 /* address bits */ -#define MAXMEMSIZE (1u << ADDRSIZE) /* max mem size */ -#define ADDRMASK (MAXMEMSIZE - 1) /* address mask */ -#define DAMASK 007777 /* direct addr */ -#define EPCMASK (ADDRMASK & ~DAMASK) /* extended addr */ -#define IA 010000 /* indirect flag */ -#define IO_WAIT 010000 /* I/O sync wait */ -#define IO_CPLS 004000 /* cmopletion pulse */ -#define GEN_CPLS(x) (((x) ^ ((x) << 1)) & IO_WAIT) /* completion pulse? */ -#define MEMSIZE (cpu_unit.capac) /* actual memory size */ -#define MEM_ADDR_OK(x) (((t_addr) (x)) < MEMSIZE) - /* Simulator stop codes */ #define STOP_RSRV 1 /* must be 1 */ @@ -60,6 +46,23 @@ #define STOP_XCT 4 /* nested XCT's */ #define STOP_IND 5 /* nested indirects */ #define STOP_WAIT 6 /* wait state */ + +/* Memory */ + +#define ASIZE 16 /* address bits */ +#define MAXMEMSIZE (1u << ASIZE) /* max mem size */ +#define AMASK (MAXMEMSIZE - 1) /* address mask */ +#define MEMSIZE (cpu_unit.capac) /* actual memory size */ +#define MEM_ADDR_OK(x) (((t_addr) (x)) < MEMSIZE) + +/* Architectural constants */ + +#define DAMASK 007777 /* direct addr */ +#define EPCMASK (AMASK & ~DAMASK) /* extended addr */ +#define IA 010000 /* indirect flag */ +#define IO_WAIT 010000 /* I/O sync wait */ +#define IO_CPLS 004000 /* cmopletion pulse */ +#define GEN_CPLS(x) (((x) ^ ((x) << 1)) & IO_WAIT) /* completion pulse? */ /* IOT subroutine return codes */ diff --git a/pdp1_lp.c b/pdp1_lp.c index 2d84288d..4ed133e8 100644 --- a/pdp1_lp.c +++ b/pdp1_lp.c @@ -1,6 +1,6 @@ /* pdp1_lp.c: PDP-1 line printer simulator - Copyright (c) 1993-1999, Robert M. Supnik + Copyright (c) 1993-2000, 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"), diff --git a/pdp1_sys.c b/pdp1_sys.c index 73ecb769..6a837dd1 100644 --- a/pdp1_sys.c +++ b/pdp1_sys.c @@ -409,7 +409,7 @@ case I_V_MRF: case I_V_MRI: /* mem ref */ if ((j != I_V_MRI) && strcmp (gbuf, "I") == 0) { /* indirect? */ val[0] = val[0] | IA; cptr = get_glyph (cptr, gbuf, 0); } - d = get_uint (gbuf, 8, ADDRMASK, &r); + d = get_uint (gbuf, 8, AMASK, &r); if (r != SCPE_OK) return SCPE_ARG; if (d <= DAMASK) val[0] = val[0] | d; else if (cflag && (((addr ^ d) & EPCMASK) == 0)) diff --git a/pdp8_defs.h b/pdp8_defs.h index 27ef7928..7ac848d2 100644 --- a/pdp8_defs.h +++ b/pdp8_defs.h @@ -33,6 +33,12 @@ #include "sim_defs.h" /* simulator defns */ +/* Simulator stop codes */ + +#define STOP_RSRV 1 /* must be 1 */ +#define STOP_HALT 2 /* HALT */ +#define STOP_IBKPT 3 /* breakpoint */ + /* Memory */ #define MAXMEMSIZE 32768 /* max memory size */ @@ -40,12 +46,6 @@ #define ADDRMASK (MAXMEMSIZE - 1) /* address mask */ #define MEM_ADDR_OK(x) (((t_addr) (x)) < MEMSIZE) -/* Simulator stop codes */ - -#define STOP_RSRV 1 /* must be 1 */ -#define STOP_HALT 2 /* HALT */ -#define STOP_IBKPT 3 /* breakpoint */ - /* IOT subroutine return codes */ #define IOT_V_SKP 12 /* skip */ diff --git a/scp.c b/scp.c index 5cec04da..9607d097 100644 --- a/scp.c +++ b/scp.c @@ -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. + 22-Dec-00 RMS Fixed find_device for devices ending in numbers + 08-Dec-00 RMS V2.5a changes 30-Oct-00 RMS Added output file option to examine 11-Jul-99 RMS V2.5 changes 13-Apr-99 RMS Fixed handling of 32b addresses @@ -259,7 +261,7 @@ static CTAB cmd_table[] = { /* Main command loop */ -printf ("\n%s simulator V2.5\n", sim_name); +printf ("\n%s simulator V2.5a\n", sim_name); end_test.i = 1; /* test endian-ness */ sim_end = end_test.c[0]; if (sim_emax <= 0) sim_emax = 1; @@ -1656,7 +1658,12 @@ int32 i, lenn, unitno; t_stat r; DEVICE *dptr; -for (i = 0; (dptr = sim_devices[i]) != NULL; i++) { +for (i = 0; (dptr = sim_devices[i]) != NULL; i++) { /* exact match? */ + if (strcmp (cptr, dptr -> name) != 0) continue; + if (iptr != NULL) *iptr = 0; + return sim_devices[i]; } + +for (i = 0; (dptr = sim_devices[i]) != NULL; i++) { /* base + unit#? */ lenn = strlen (dptr -> name); if (strncmp (cptr, dptr -> name, lenn) != 0) continue; cptr = cptr + lenn; diff --git a/scp_tty.c b/scp_tty.c index 165063a1..0a4a84f3 100644 --- a/scp_tty.c +++ b/scp_tty.c @@ -1,6 +1,6 @@ /* scp_tty.c: Operating system-dependent terminal I/O routines. - Copyright (c) 1993-1999, Robert M Supnik + Copyright (c) 1993-2000, 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,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. + 08-Dec-00 BKR Added OS/2 support 18-Aug-98 RMS Added BeOS support 13-Oct-97 RMS Added NetBSD terminal support 25-Jan-97 RMS Added POSIX terminal I/O support @@ -189,6 +190,52 @@ _putch (c); return SCPE_OK; } +#endif + +/* OS/2 routines */ + +#ifdef __OS2__ +#define __TTYROUTINES 0 +#include + +t_stat ttinit (void) +{ +return SCPE_OK; +} + +t_stat ttrunstate (void) +{ +return SCPE_OK; +} + +t_stat ttcmdstate (void) +{ +return SCPE_OK; +} + +t_stat ttclose (void) +{ +return SCPE_OK; +} + +t_stat sim_poll_kbd (void) +{ +int c; + +if (!kbhit ()) return SCPE_OK; +c = getch(); +if ((c & 0177) == '\b') c = 0177; +if ((c & 0177) == sim_int_char) return SCPE_STOP; +return c | SCPE_KFLAG; +} + +t_stat sim_putchar (int32 c) +{ +putch (c); +fflush (stdout) ; +return SCPE_OK; +} + #endif /* BSD UNIX routines */ diff --git a/simh.doc b/simh.doc index 284935ea..9a262c0c 100644 --- a/simh.doc +++ b/simh.doc @@ -1,81 +1,84 @@ {\rtf1\ansi\ansicpg1252\uc1 \deff0\deflang1033\deflangfe1033{\fonttbl{\f0\froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f1\fswiss\fcharset0\fprq2{\*\panose 020b0604020202020204}Arial;} {\f3\froman\fcharset2\fprq2{\*\panose 05050102010706020507}Symbol;}{\f16\froman\fcharset238\fprq2 Times New Roman CE;}{\f17\froman\fcharset204\fprq2 Times New Roman Cyr;}{\f19\froman\fcharset161\fprq2 Times New Roman Greek;} -{\f20\froman\fcharset162\fprq2 Times New Roman Tur;}{\f21\froman\fcharset186\fprq2 Times New Roman Baltic;}}{\colortbl;\red0\green0\blue0;\red0\green0\blue255;\red0\green255\blue255;\red0\green255\blue0;\red255\green0\blue255;\red255\green0\blue0; -\red255\green255\blue0;\red255\green255\blue255;\red0\green0\blue128;\red0\green128\blue128;\red0\green128\blue0;\red128\green0\blue128;\red128\green0\blue0;\red128\green128\blue0;\red128\green128\blue128;\red192\green192\blue192;}{\stylesheet{ -\widctlpar\adjustright \fs20\cgrid \snext0 Normal;}{\*\cs10 \additive Default Paragraph Font;}}{\*\listtable{\list\listtemplateid1706078190\listsimple{\listlevel\levelnfc23\leveljc0\levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext -\'01\u-3913 ?;}{\levelnumbers;}\f3\fbias0 \fi-360\li720\jclisttab\tx720 }{\listname ;}\listid22442644}{\list\listtemplateid-1866037950{\listlevel\levelnfc0\leveljc0\levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext\'02\'00.;}{\levelnumbers -\'01;}\fbias0 \fi-360\li360\jclisttab\tx360 }{\listlevel\levelnfc0\leveljc0\levelfollow0\levelstartat1\levellegal\levelspace0\levelindent0{\leveltext\'03\'00.\'01;}{\levelnumbers\'01\'03;}\fbias0 \fi-360\li360\jclisttab\tx360 }{\listlevel\levelnfc0 -\leveljc0\levelfollow0\levelstartat1\levellegal\levelspace0\levelindent0{\leveltext\'05\'00.\'01.\'02;}{\levelnumbers\'01\'03\'05;}\fbias0 \fi-720\li720\jclisttab\tx720 }{\listlevel\levelnfc0\leveljc0\levelfollow0\levelstartat1\levellegal\levelspace0 -\levelindent0{\leveltext\'07\'00.\'01.\'02.\'03;}{\levelnumbers\'01\'03\'05\'07;}\fbias0 \fi-720\li720\jclisttab\tx720 }{\listlevel\levelnfc0\leveljc0\levelfollow0\levelstartat1\levellegal\levelspace0\levelindent0{\leveltext -\'09\'00.\'01.\'02.\'03.\'04;}{\levelnumbers\'01\'03\'05\'07\'09;}\fbias0 \fi-720\li720\jclisttab\tx720 }{\listlevel\levelnfc0\leveljc0\levelfollow0\levelstartat1\levellegal\levelspace0\levelindent0{\leveltext +{\f20\froman\fcharset162\fprq2 Times New Roman Tur;}{\f21\froman\fcharset186\fprq2 Times New Roman Baltic;}{\f22\fswiss\fcharset238\fprq2 Arial CE;}{\f23\fswiss\fcharset204\fprq2 Arial Cyr;}{\f25\fswiss\fcharset161\fprq2 Arial Greek;} +{\f26\fswiss\fcharset162\fprq2 Arial Tur;}{\f27\fswiss\fcharset186\fprq2 Arial Baltic;}}{\colortbl;\red0\green0\blue0;\red0\green0\blue255;\red0\green255\blue255;\red0\green255\blue0;\red255\green0\blue255;\red255\green0\blue0;\red255\green255\blue0; +\red255\green255\blue255;\red0\green0\blue128;\red0\green128\blue128;\red0\green128\blue0;\red128\green0\blue128;\red128\green0\blue0;\red128\green128\blue0;\red128\green128\blue128;\red192\green192\blue192;}{\stylesheet{\widctlpar\adjustright +\fs20\cgrid \snext0 Normal;}{\*\cs10 \additive Default Paragraph Font;}}{\*\listtable{\list\listtemplateid1706078190\listsimple{\listlevel\levelnfc23\leveljc0\levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext\'01\u-3913 ?;}{\levelnumbers;} +\f3\fbias0 \fi-360\li720\jclisttab\tx720 }{\listname ;}\listid22442644}{\list\listtemplateid-1866037950{\listlevel\levelnfc0\leveljc0\levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext\'02\'00.;}{\levelnumbers\'01;}\fbias0 \fi-360\li360 +\jclisttab\tx360 }{\listlevel\levelnfc0\leveljc0\levelfollow0\levelstartat1\levellegal\levelspace0\levelindent0{\leveltext\'03\'00.\'01;}{\levelnumbers\'01\'03;}\fbias0 \fi-360\li360\jclisttab\tx360 }{\listlevel\levelnfc0\leveljc0\levelfollow0 +\levelstartat1\levellegal\levelspace0\levelindent0{\leveltext\'05\'00.\'01.\'02;}{\levelnumbers\'01\'03\'05;}\fbias0 \fi-720\li720\jclisttab\tx720 }{\listlevel\levelnfc0\leveljc0\levelfollow0\levelstartat1\levellegal\levelspace0\levelindent0{\leveltext +\'07\'00.\'01.\'02.\'03;}{\levelnumbers\'01\'03\'05\'07;}\fbias0 \fi-720\li720\jclisttab\tx720 }{\listlevel\levelnfc0\leveljc0\levelfollow0\levelstartat1\levellegal\levelspace0\levelindent0{\leveltext\'09\'00.\'01.\'02.\'03.\'04;}{\levelnumbers +\'01\'03\'05\'07\'09;}\fbias0 \fi-720\li720\jclisttab\tx720 }{\listlevel\levelnfc0\leveljc0\levelfollow0\levelstartat1\levellegal\levelspace0\levelindent0{\leveltext\'0b\'00.\'01.\'02.\'03.\'04.\'05;}{\levelnumbers\'01\'03\'05\'07\'09\'0b;}\fbias0 +\fi-1080\li1080\jclisttab\tx1080 }{\listlevel\levelnfc0\leveljc0\levelfollow0\levelstartat1\levellegal\levelspace0\levelindent0{\leveltext\'0d\'00.\'01.\'02.\'03.\'04.\'05.\'06;}{\levelnumbers\'01\'03\'05\'07\'09\'0b\'0d;}\fbias0 \fi-1080\li1080 +\jclisttab\tx1080 }{\listlevel\levelnfc0\leveljc0\levelfollow0\levelstartat1\levellegal\levelspace0\levelindent0{\leveltext\'0f\'00.\'01.\'02.\'03.\'04.\'05.\'06.\'07;}{\levelnumbers\'01\'03\'05\'07\'09\'0b\'0d\'0f;}\fbias0 \fi-1440\li1440 +\jclisttab\tx1440 }{\listlevel\levelnfc0\leveljc0\levelfollow0\levelstartat1\levellegal\levelspace0\levelindent0{\leveltext\'11\'00.\'01.\'02.\'03.\'04.\'05.\'06.\'07.\'08;}{\levelnumbers\'01\'03\'05\'07\'09\'0b\'0d\'0f\'11;}\fbias0 \fi-1440\li1440 +\jclisttab\tx1440 }{\listname ;}\listid155609463}{\list\listtemplateid1706078190\listsimple{\listlevel\levelnfc23\leveljc0\levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext\'01\u-3913 ?;}{\levelnumbers;}\f3\fbias0 \fi-360\li720 +\jclisttab\tx720 }{\listname ;}\listid602111040}{\list\listtemplateid1706078190\listsimple{\listlevel\levelnfc23\leveljc0\levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext\'01\u-3913 ?;}{\levelnumbers;}\f3\fbias0 \fi-360\li720 +\jclisttab\tx720 }{\listname ;}\listid621424954}{\list\listtemplateid1706078190\listsimple{\listlevel\levelnfc23\leveljc0\levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext\'01\u-3913 ?;}{\levelnumbers;}\f3\fbias0 \fi-360\li720 +\jclisttab\tx720 }{\listname ;}\listid717362522}{\list\listtemplateid1706078190\listsimple{\listlevel\levelnfc23\leveljc0\levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext\'01\u-3913 ?;}{\levelnumbers;}\f3\fbias0 \fi-360\li720 +\jclisttab\tx720 }{\listname ;}\listid1080104542}{\list\listtemplateid-5054418{\listlevel\levelnfc0\leveljc0\levelfollow0\levelstartat2\levelspace0\levelindent0{\leveltext\'01\'00;}{\levelnumbers\'01;}\fbias0 \fi-435\li435\jclisttab\tx435 }{\listlevel +\levelnfc0\leveljc0\levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext\'03\'00.\'01;}{\levelnumbers\'01\'03;}\fbias0 \fi-435\li435\jclisttab\tx435 }{\listlevel\levelnfc0\leveljc0\levelfollow0\levelstartat2\levelspace0\levelindent0{\leveltext +\'05\'00.\'01.\'02;}{\levelnumbers\'01\'03\'05;}\fbias0 \fi-720\li720\jclisttab\tx720 }{\listlevel\levelnfc0\leveljc0\levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext\'07\'00.\'01.\'02.\'03;}{\levelnumbers\'01\'03\'05\'07;}\fbias0 +\fi-720\li720\jclisttab\tx720 }{\listlevel\levelnfc0\leveljc0\levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext\'09\'00.\'01.\'02.\'03.\'04;}{\levelnumbers\'01\'03\'05\'07\'09;}\fbias0 \fi-1080\li1080\jclisttab\tx1080 }{\listlevel\levelnfc0 +\leveljc0\levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext\'0b\'00.\'01.\'02.\'03.\'04.\'05;}{\levelnumbers\'01\'03\'05\'07\'09\'0b;}\fbias0 \fi-1080\li1080\jclisttab\tx1080 }{\listlevel\levelnfc0\leveljc0\levelfollow0\levelstartat1 +\levelspace0\levelindent0{\leveltext\'0d\'00.\'01.\'02.\'03.\'04.\'05.\'06;}{\levelnumbers\'01\'03\'05\'07\'09\'0b\'0d;}\fbias0 \fi-1440\li1440\jclisttab\tx1440 }{\listlevel\levelnfc0\leveljc0\levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext +\'0f\'00.\'01.\'02.\'03.\'04.\'05.\'06.\'07;}{\levelnumbers\'01\'03\'05\'07\'09\'0b\'0d\'0f;}\fbias0 \fi-1440\li1440\jclisttab\tx1440 }{\listlevel\levelnfc0\leveljc0\levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext +\'11\'00.\'01.\'02.\'03.\'04.\'05.\'06.\'07.\'08;}{\levelnumbers\'01\'03\'05\'07\'09\'0b\'0d\'0f\'11;}\fbias0 \fi-1800\li1800\jclisttab\tx1800 }{\listname ;}\listid1262834005}{\list\listtemplateid1706078190\listsimple{\listlevel\levelnfc23\leveljc0 +\levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext\'01\u-3913 ?;}{\levelnumbers;}\f3\fbias0 \fi-360\li720\jclisttab\tx720 }{\listname ;}\listid1272592440}{\list\listtemplateid1706078190\listsimple{\listlevel\levelnfc23\leveljc0\levelfollow0 +\levelstartat1\levelspace0\levelindent0{\leveltext\'01\u-3913 ?;}{\levelnumbers;}\f3\fbias0 \fi-360\li720\jclisttab\tx720 }{\listname ;}\listid1339387548}{\list\listtemplateid1706078190\listsimple{\listlevel\levelnfc23\leveljc0\levelfollow0\levelstartat1 +\levelspace0\levelindent0{\leveltext\'01\u-3913 ?;}{\levelnumbers;}\f3\fbias0 \fi-360\li720\jclisttab\tx720 }{\listname ;}\listid1409111490}{\list\listtemplateid230209238{\listlevel\levelnfc0\leveljc0\levelfollow0\levelstartat3\levelspace0\levelindent0 +{\leveltext\'02\'00.;}{\levelnumbers\'01;}\fbias0 \fi-360\li360\jclisttab\tx360 }{\listlevel\levelnfc0\leveljc0\levelfollow0\levelstartat1\levellegal\levelspace0\levelindent0{\leveltext\'03\'00.\'01;}{\levelnumbers\'01\'03;}\fbias0 \fi-360\li360 +\jclisttab\tx360 }{\listlevel\levelnfc0\leveljc0\levelfollow0\levelstartat1\levellegal\levelspace0\levelindent0{\leveltext\'05\'00.\'01.\'02;}{\levelnumbers\'01\'03\'05;}\fbias0 \fi-720\li720\jclisttab\tx720 }{\listlevel\levelnfc0\leveljc0\levelfollow0 +\levelstartat1\levellegal\levelspace0\levelindent0{\leveltext\'07\'00.\'01.\'02.\'03;}{\levelnumbers\'01\'03\'05\'07;}\fbias0 \fi-720\li720\jclisttab\tx720 }{\listlevel\levelnfc0\leveljc0\levelfollow0\levelstartat1\levellegal\levelspace0\levelindent0 +{\leveltext\'09\'00.\'01.\'02.\'03.\'04;}{\levelnumbers\'01\'03\'05\'07\'09;}\fbias0 \fi-720\li720\jclisttab\tx720 }{\listlevel\levelnfc0\leveljc0\levelfollow0\levelstartat1\levellegal\levelspace0\levelindent0{\leveltext \'0b\'00.\'01.\'02.\'03.\'04.\'05;}{\levelnumbers\'01\'03\'05\'07\'09\'0b;}\fbias0 \fi-1080\li1080\jclisttab\tx1080 }{\listlevel\levelnfc0\leveljc0\levelfollow0\levelstartat1\levellegal\levelspace0\levelindent0{\leveltext \'0d\'00.\'01.\'02.\'03.\'04.\'05.\'06;}{\levelnumbers\'01\'03\'05\'07\'09\'0b\'0d;}\fbias0 \fi-1080\li1080\jclisttab\tx1080 }{\listlevel\levelnfc0\leveljc0\levelfollow0\levelstartat1\levellegal\levelspace0\levelindent0{\leveltext \'0f\'00.\'01.\'02.\'03.\'04.\'05.\'06.\'07;}{\levelnumbers\'01\'03\'05\'07\'09\'0b\'0d\'0f;}\fbias0 \fi-1440\li1440\jclisttab\tx1440 }{\listlevel\levelnfc0\leveljc0\levelfollow0\levelstartat1\levellegal\levelspace0\levelindent0{\leveltext -\'11\'00.\'01.\'02.\'03.\'04.\'05.\'06.\'07.\'08;}{\levelnumbers\'01\'03\'05\'07\'09\'0b\'0d\'0f\'11;}\fbias0 \fi-1440\li1440\jclisttab\tx1440 }{\listname ;}\listid155609463}{\list\listtemplateid1706078190\listsimple{\listlevel\levelnfc23\leveljc0 -\levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext\'01\u-3913 ?;}{\levelnumbers;}\f3\fbias0 \fi-360\li720\jclisttab\tx720 }{\listname ;}\listid602111040}{\list\listtemplateid1706078190\listsimple{\listlevel\levelnfc23\leveljc0\levelfollow0 -\levelstartat1\levelspace0\levelindent0{\leveltext\'01\u-3913 ?;}{\levelnumbers;}\f3\fbias0 \fi-360\li720\jclisttab\tx720 }{\listname ;}\listid621424954}{\list\listtemplateid1706078190\listsimple{\listlevel\levelnfc23\leveljc0\levelfollow0\levelstartat1 -\levelspace0\levelindent0{\leveltext\'01\u-3913 ?;}{\levelnumbers;}\f3\fbias0 \fi-360\li720\jclisttab\tx720 }{\listname ;}\listid717362522}{\list\listtemplateid1706078190\listsimple{\listlevel\levelnfc23\leveljc0\levelfollow0\levelstartat1\levelspace0 -\levelindent0{\leveltext\'01\u-3913 ?;}{\levelnumbers;}\f3\fbias0 \fi-360\li720\jclisttab\tx720 }{\listname ;}\listid1080104542}{\list\listtemplateid-5054418{\listlevel\levelnfc0\leveljc0\levelfollow0\levelstartat2\levelspace0\levelindent0{\leveltext -\'01\'00;}{\levelnumbers\'01;}\fbias0 \fi-435\li435\jclisttab\tx435 }{\listlevel\levelnfc0\leveljc0\levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext\'03\'00.\'01;}{\levelnumbers\'01\'03;}\fbias0 \fi-435\li435\jclisttab\tx435 }{\listlevel -\levelnfc0\leveljc0\levelfollow0\levelstartat2\levelspace0\levelindent0{\leveltext\'05\'00.\'01.\'02;}{\levelnumbers\'01\'03\'05;}\fbias0 \fi-720\li720\jclisttab\tx720 }{\listlevel\levelnfc0\leveljc0\levelfollow0\levelstartat1\levelspace0\levelindent0 -{\leveltext\'07\'00.\'01.\'02.\'03;}{\levelnumbers\'01\'03\'05\'07;}\fbias0 \fi-720\li720\jclisttab\tx720 }{\listlevel\levelnfc0\leveljc0\levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext\'09\'00.\'01.\'02.\'03.\'04;}{\levelnumbers -\'01\'03\'05\'07\'09;}\fbias0 \fi-1080\li1080\jclisttab\tx1080 }{\listlevel\levelnfc0\leveljc0\levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext\'0b\'00.\'01.\'02.\'03.\'04.\'05;}{\levelnumbers\'01\'03\'05\'07\'09\'0b;}\fbias0 \fi-1080\li1080 -\jclisttab\tx1080 }{\listlevel\levelnfc0\leveljc0\levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext\'0d\'00.\'01.\'02.\'03.\'04.\'05.\'06;}{\levelnumbers\'01\'03\'05\'07\'09\'0b\'0d;}\fbias0 \fi-1440\li1440\jclisttab\tx1440 }{\listlevel -\levelnfc0\leveljc0\levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext\'0f\'00.\'01.\'02.\'03.\'04.\'05.\'06.\'07;}{\levelnumbers\'01\'03\'05\'07\'09\'0b\'0d\'0f;}\fbias0 \fi-1440\li1440\jclisttab\tx1440 }{\listlevel\levelnfc0\leveljc0 -\levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext\'11\'00.\'01.\'02.\'03.\'04.\'05.\'06.\'07.\'08;}{\levelnumbers\'01\'03\'05\'07\'09\'0b\'0d\'0f\'11;}\fbias0 \fi-1800\li1800\jclisttab\tx1800 }{\listname ;}\listid1262834005} -{\list\listtemplateid1706078190\listsimple{\listlevel\levelnfc23\leveljc0\levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext\'01\u-3913 ?;}{\levelnumbers;}\f3\fbias0 \fi-360\li720\jclisttab\tx720 }{\listname ;}\listid1272592440} -{\list\listtemplateid1706078190\listsimple{\listlevel\levelnfc23\leveljc0\levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext\'01\u-3913 ?;}{\levelnumbers;}\f3\fbias0 \fi-360\li720\jclisttab\tx720 }{\listname ;}\listid1339387548} -{\list\listtemplateid1706078190\listsimple{\listlevel\levelnfc23\leveljc0\levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext\'01\u-3913 ?;}{\levelnumbers;}\f3\fbias0 \fi-360\li720\jclisttab\tx720 }{\listname ;}\listid1409111490} -{\list\listtemplateid230209238{\listlevel\levelnfc0\leveljc0\levelfollow0\levelstartat3\levelspace0\levelindent0{\leveltext\'02\'00.;}{\levelnumbers\'01;}\fbias0 \fi-360\li360\jclisttab\tx360 }{\listlevel\levelnfc0\leveljc0\levelfollow0\levelstartat1 -\levellegal\levelspace0\levelindent0{\leveltext\'03\'00.\'01;}{\levelnumbers\'01\'03;}\fbias0 \fi-360\li360\jclisttab\tx360 }{\listlevel\levelnfc0\leveljc0\levelfollow0\levelstartat1\levellegal\levelspace0\levelindent0{\leveltext -\'05\'00.\'01.\'02;}{\levelnumbers\'01\'03\'05;}\fbias0 \fi-720\li720\jclisttab\tx720 }{\listlevel\levelnfc0\leveljc0\levelfollow0\levelstartat1\levellegal\levelspace0\levelindent0{\leveltext\'07\'00.\'01.\'02.\'03;}{\levelnumbers\'01\'03\'05\'07;} -\fbias0 \fi-720\li720\jclisttab\tx720 }{\listlevel\levelnfc0\leveljc0\levelfollow0\levelstartat1\levellegal\levelspace0\levelindent0{\leveltext\'09\'00.\'01.\'02.\'03.\'04;}{\levelnumbers\'01\'03\'05\'07\'09;}\fbias0 \fi-720\li720\jclisttab\tx720 } -{\listlevel\levelnfc0\leveljc0\levelfollow0\levelstartat1\levellegal\levelspace0\levelindent0{\leveltext\'0b\'00.\'01.\'02.\'03.\'04.\'05;}{\levelnumbers\'01\'03\'05\'07\'09\'0b;}\fbias0 \fi-1080\li1080\jclisttab\tx1080 }{\listlevel\levelnfc0\leveljc0 -\levelfollow0\levelstartat1\levellegal\levelspace0\levelindent0{\leveltext\'0d\'00.\'01.\'02.\'03.\'04.\'05.\'06;}{\levelnumbers\'01\'03\'05\'07\'09\'0b\'0d;}\fbias0 \fi-1080\li1080\jclisttab\tx1080 }{\listlevel\levelnfc0\leveljc0\levelfollow0 -\levelstartat1\levellegal\levelspace0\levelindent0{\leveltext\'0f\'00.\'01.\'02.\'03.\'04.\'05.\'06.\'07;}{\levelnumbers\'01\'03\'05\'07\'09\'0b\'0d\'0f;}\fbias0 \fi-1440\li1440\jclisttab\tx1440 }{\listlevel\levelnfc0\leveljc0\levelfollow0\levelstartat1 -\levellegal\levelspace0\levelindent0{\leveltext\'11\'00.\'01.\'02.\'03.\'04.\'05.\'06.\'07.\'08;}{\levelnumbers\'01\'03\'05\'07\'09\'0b\'0d\'0f\'11;}\fbias0 \fi-1440\li1440\jclisttab\tx1440 }{\listname ;}\listid1502426668}{\list\listtemplateid1706078190 -\listsimple{\listlevel\levelnfc23\leveljc0\levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext\'01\u-3913 ?;}{\levelnumbers;}\f3\fbias0 \fi-360\li720\jclisttab\tx720 }{\listname ;}\listid1645162521}{\list\listtemplateid1706078190\listsimple -{\listlevel\levelnfc23\leveljc0\levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext\'01\u-3913 ?;}{\levelnumbers;}\f3\fbias0 \fi-360\li720\jclisttab\tx720 }{\listname ;}\listid2006126440}{\list\listtemplateid1706078190\listsimple{\listlevel -\levelnfc23\leveljc0\levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext\'01\u-3913 ?;}{\levelnumbers;}\f3\fbias0 \fi-360\li720\jclisttab\tx720 }{\listname ;}\listid2076124660}}{\*\listoverridetable{\listoverride\listid155609463 -\listoverridecount0\ls1}{\listoverride\listid1409111490\listoverridecount0\ls2}{\listoverride\listid1272592440\listoverridecount0\ls3}{\listoverride\listid2076124660\listoverridecount0\ls4}{\listoverride\listid717362522\listoverridecount0\ls5} -{\listoverride\listid1339387548\listoverridecount0\ls6}{\listoverride\listid621424954\listoverridecount0\ls7}{\listoverride\listid1080104542\listoverridecount0\ls8}{\listoverride\listid1262834005\listoverridecount0\ls9}{\listoverride\listid2006126440 -\listoverridecount0\ls10}{\listoverride\listid602111040\listoverridecount0\ls11}{\listoverride\listid22442644\listoverridecount0\ls12}{\listoverride\listid1502426668\listoverridecount0\ls13}{\listoverride\listid1645162521\listoverridecount0\ls14}}{\info -{\title Writing a Simulator for the SIMH System}{\author Bob Supnik}{\operator Bob Supnik}{\creatim\yr1997\mo8\dy30\hr19}{\revtim\yr2000\mo11\dy18\hr18\min39}{\version10}{\edmins391}{\nofpages15}{\nofwords5229}{\nofchars29808} -{\*\company Digital Equipment Corporation}{\nofcharsws0}{\vern113}}\widowctrl\ftnbj\aenddoc\hyphcaps0\formshade\viewkind4\viewscale100\pgbrdrhead\pgbrdrfoot \fet0\sectd \linex0\endnhere\sectdefaultcl {\*\pnseclvl1\pnucrm\pnstart1\pnindent720\pnhang -{\pntxta .}}{\*\pnseclvl2\pnucltr\pnstart1\pnindent720\pnhang{\pntxta .}}{\*\pnseclvl3\pndec\pnstart1\pnindent720\pnhang{\pntxta .}}{\*\pnseclvl4\pnlcltr\pnstart1\pnindent720\pnhang{\pntxta )}}{\*\pnseclvl5\pndec\pnstart1\pnindent720\pnhang{\pntxtb (} -{\pntxta )}}{\*\pnseclvl6\pnlcltr\pnstart1\pnindent720\pnhang{\pntxtb (}{\pntxta )}}{\*\pnseclvl7\pnlcrm\pnstart1\pnindent720\pnhang{\pntxtb (}{\pntxta )}}{\*\pnseclvl8\pnlcltr\pnstart1\pnindent720\pnhang{\pntxtb (}{\pntxta )}}{\*\pnseclvl9 -\pnlcrm\pnstart1\pnindent720\pnhang{\pntxtb (}{\pntxta )}}\pard\plain \widctlpar\adjustright \fs20\cgrid {\f1 Writing a Simulator for the SIMH System -\par Revised 30-Oct-00 for V2.5 +\'11\'00.\'01.\'02.\'03.\'04.\'05.\'06.\'07.\'08;}{\levelnumbers\'01\'03\'05\'07\'09\'0b\'0d\'0f\'11;}\fbias0 \fi-1440\li1440\jclisttab\tx1440 }{\listname ;}\listid1502426668}{\list\listtemplateid1706078190\listsimple{\listlevel\levelnfc23\leveljc0 +\levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext\'01\u-3913 ?;}{\levelnumbers;}\f3\fbias0 \fi-360\li720\jclisttab\tx720 }{\listname ;}\listid1645162521}{\list\listtemplateid1706078190\listsimple{\listlevel\levelnfc23\leveljc0\levelfollow0 +\levelstartat1\levelspace0\levelindent0{\leveltext\'01\u-3913 ?;}{\levelnumbers;}\f3\fbias0 \fi-360\li720\jclisttab\tx720 }{\listname ;}\listid2006126440}{\list\listtemplateid1706078190\listsimple{\listlevel\levelnfc23\leveljc0\levelfollow0\levelstartat1 +\levelspace0\levelindent0{\leveltext\'01\u-3913 ?;}{\levelnumbers;}\f3\fbias0 \fi-360\li720\jclisttab\tx720 }{\listname ;}\listid2076124660}}{\*\listoverridetable{\listoverride\listid155609463\listoverridecount0\ls1}{\listoverride\listid1409111490 +\listoverridecount0\ls2}{\listoverride\listid1272592440\listoverridecount0\ls3}{\listoverride\listid2076124660\listoverridecount0\ls4}{\listoverride\listid717362522\listoverridecount0\ls5}{\listoverride\listid1339387548\listoverridecount0\ls6} +{\listoverride\listid621424954\listoverridecount0\ls7}{\listoverride\listid1080104542\listoverridecount0\ls8}{\listoverride\listid1262834005\listoverridecount0\ls9}{\listoverride\listid2006126440\listoverridecount0\ls10}{\listoverride\listid602111040 +\listoverridecount0\ls11}{\listoverride\listid22442644\listoverridecount0\ls12}{\listoverride\listid1502426668\listoverridecount0\ls13}{\listoverride\listid1645162521\listoverridecount0\ls14}}{\info{\title Writing a Simulator for the SIMH System} +{\author Bob Supnik}{\operator Bob Supnik}{\creatim\yr1997\mo8\dy30\hr19}{\revtim\yr2000\mo12\dy16\hr23\min48}{\version12}{\edmins414}{\nofpages15}{\nofwords5229}{\nofchars29808}{\*\company Digital Equipment Corporation}{\nofcharsws0}{\vern113}} +\widowctrl\ftnbj\aenddoc\hyphcaps0\formshade\viewkind4\viewscale100\pgbrdrhead\pgbrdrfoot \fet0\sectd \linex0\endnhere\sectdefaultcl {\*\pnseclvl1\pnucrm\pnstart1\pnindent720\pnhang{\pntxta .}}{\*\pnseclvl2\pnucltr\pnstart1\pnindent720\pnhang{\pntxta .}} +{\*\pnseclvl3\pndec\pnstart1\pnindent720\pnhang{\pntxta .}}{\*\pnseclvl4\pnlcltr\pnstart1\pnindent720\pnhang{\pntxta )}}{\*\pnseclvl5\pndec\pnstart1\pnindent720\pnhang{\pntxtb (}{\pntxta )}}{\*\pnseclvl6\pnlcltr\pnstart1\pnindent720\pnhang{\pntxtb (} +{\pntxta )}}{\*\pnseclvl7\pnlcrm\pnstart1\pnindent720\pnhang{\pntxtb (}{\pntxta )}}{\*\pnseclvl8\pnlcltr\pnstart1\pnindent720\pnhang{\pntxtb (}{\pntxta )}}{\*\pnseclvl9\pnlcrm\pnstart1\pnindent720\pnhang{\pntxtb (}{\pntxta )}}\pard\plain +\widctlpar\adjustright \fs20\cgrid {\f1 Writing a Simulator for the SIMH System +\par Revised 30-Nov-00 for V2.5a \par \par {\listtext\pard\plain\f1\fs20\cgrid \hich\af1\dbch\af0\loch\f1 1.\tab}}\pard \fi-360\li360\widctlpar\jclisttab\tx360\ls1\adjustright {\f1 Overview \par }\pard \widctlpar\adjustright {\f1 -\par SIMH (history simulators) is a set of portable programs, written in C, which simulate various historically interesting computers. This document describes how to design, write, a -nd check out a new simulator for SIMH. It is not an introduction to either the philosophy or external operation of SIMH, and the reader should be familiar with both of those topics before proceeding. Nor is it a guide to the internal design or operation - -of SIMH, except insofar as those areas interact with simulator design. Instead, this manual presents and explains the form, meaning, and operation of the interfaces between simulators and the SIMH simulator control package. It also offers some suggestio -ns for utilizing the services SIMH offers and explains the constraints which all simulators operating within SIMH will experience. +\par SIMH (history simulators) is a set of portable programs, written in C, which simulate various historically interesting computers. This document describes how to design, write, and check out a new simulator for SIMH. It is not an introduction to either t +h +e philosophy or external operation of SIMH, and the reader should be familiar with both of those topics before proceeding. Nor is it a guide to the internal design or operation of SIMH, except insofar as those areas interact with simulator design. Inste +a +d, this manual presents and explains the form, meaning, and operation of the interfaces between simulators and the SIMH simulator control package. It also offers some suggestions for utilizing the services SIMH offers and explains the constraints which a +ll simulators operating within SIMH will experience. \par -\par Some terminology: Each simulator consists of a standard }{\i\f1 simulator control package}{\f1 (SCP), which provides a control framework and utility routines for a simulator; and a unique }{\i\f1 virtual machine}{\f1 - (VM), which implements the simulated processor and selected peripherals. A VM consists of multiple }{\i\f1 devices}{\f1 , such as the CPU, paper tape reader, disk controller, etc. Each controller consists of a named state space (called }{\i\f1 -registers}{\f1 ) and one or more }{\i\f1 units}{\f1 . Each unit consists of a numbered state space (called a }{\i\f1 data set}{\f1 ). }{\i\f1 }{\f1 The }{\i\f1 host computer}{\f1 is the system on which SIMH runs; the }{\i\f1 target computer}{\f1 +\par Some terminology: Each simulator consists of a standard }{\i\f1 simulator control package}{\f1 (SCP), which provides a control framework and utility routines for a simulator; and a unique }{\i\f1 virtual machine}{\f1 (VM), which +implements the simulated processor and selected peripherals. A VM consists of multiple }{\i\f1 devices}{\f1 , such as the CPU, paper tape reader, disk controller, etc. Each controller consists of a named state space (called }{\i\f1 registers}{\f1 +) and one or more }{\i\f1 units}{\f1 . Each unit consists of a numbered state space (called a }{\i\f1 data set}{\f1 ). }{\i\f1 }{\f1 The }{\i\f1 host computer}{\f1 is the system on which SIMH runs; the }{\i\f1 target computer}{\f1 is the system being simulated. \par \par SIMH is unabashedly based on the MIMIC simulation system, designed in the late 60\rquote s by Len Fehskens, Mike McCarthy, and Bob Supnik. This document is based on MIMIC\rquote s published interface specification, \ldblquote How to Write a Virtual Machine for the MIMIC Simulation System\rdblquote , by Len Fehskens and Bob Supnik. \par -\par {\listtext\pard\plain\f1\fs20\cgrid \hich\af1\dbch\af0\loch\f1 2.\tab}}\pard \fi-360\li360\widctlpar\jclisttab\tx360\ls1\adjustright {\f1 Designing a Virtual Machine +\par {\listtext\pard\plain\f1\fs20\cgrid \hich\af1\dbch\af0\loch\f1 2.\tab}}\pard \fi-360\li360\widctlpar\jclisttab\tx360\ls1\adjustright {\f1 Data Types \par }\pard \widctlpar\adjustright {\f1 -\par SIMH is written in C. The host system must support (at least) 32-bit data types (64-bit data types for the PDP-10 and other large-word target systems). To cope with the vagaries of C data types, -SIMH defines some unambiguous data types for its interfaces: +\par SIMH is written +in C. The host system must support (at least) 32-bit data types (64-bit data types for the PDP-10 and other large-word target systems). To cope with the vagaries of C data types, SIMH defines some unambiguous data types for its interfaces: \par -\par \tab SIMH data type\tab \tab \tab interpretation in typical C +\par \tab SIMH data type\tab \tab \tab interpretation in typical 32-bit C \par -\par \tab int8\tab \tab \tab \tab char -\par \tab int16\tab \tab \tab \tab short -\par \tab int32\tab \tab \tab \tab long -\par \tab int64\tab \tab \tab \tab long long, _int64 (system specific) +\par \tab int8, uint8\tab \tab \tab char, unsigned char +\par \tab int16, uint16\tab \tab \tab short, unsigned short +\par \tab int32, uint32\tab \tab \tab int, unsigned int +\par \tab int64, uint64\tab \tab \tab long long, _int64 (system specific) \par \tab t_addr\tab \tab \tab \tab simulated address, int32 -\par \tab t_val\tab \tab \tab \tab simulated value, unsigned int32 +\par \tab t_value\tab \tab \tab \tab simulated value, unsigned int32 or int64 +\par \tab t_svalue\tab \tab \tab simulated signed value, int32 or int64 \par \tab t_mtrec\tab \tab \tab \tab mag tape record length, int32 \par \tab t_stat\tab \tab \tab \tab status code, int \par \tab t_bool\tab \tab \tab \tab true/false value, int @@ -85,6 +88,7 @@ SIMH defines some unambiguous data types for its interfaces: \par \tab }{\b\f1 DEVICE}{\f1 \tab \tab \tab device definition structure \par \tab }{\b\f1 UNIT}{\f1 \tab \tab \tab \tab unit definition structure \par \tab }{\b\f1 REG}{\f1 \tab \tab \tab \tab register definition structure +\par \tab }{\b\f1 MTAB}{\f1 \tab \tab \tab \tab modifier definition structure \par \par {\listtext\pard\plain\f1\fs20\cgrid \hich\af1\dbch\af0\loch\f1 3.\tab}}\pard \fi-360\li360\widctlpar\jclisttab\tx360\ls1\adjustright {\f1 VM Organization \par }\pard \widctlpar\adjustright {\f1 @@ -98,9 +102,9 @@ SIMH defines some unambiguous data types for its interfaces: \par \tab TTO\tab \tab \tab \tab console output \par \tab DKP\tab \tab \tab \tab disk pack controller and drives \par -\par There may -be more than one device per physical hardware entity, as for the console; but for each user-accessible device there must be at least one. One of these devices will have the pre-eminent responsibility for directing simulated operations. Normally, this is - the CPU, but it could be a higher-level entity, such as a bus master. +\par There may be more than one device per physical hardware entity, as for the console; + but for each user-accessible device there must be at least one. One of these devices will have the pre-eminent responsibility for directing simulated operations. Normally, this is the CPU, but it could be a higher-level entity, such as a bus master. + \par \par The VM actually runs as a subroutine of the simulator control package (SCP). It provides a master routine for running simulated programs and other routines and data structures to implement SCP\rquote s command and control functions. The interfaces between a VM and SCP are relatively few: @@ -112,7 +116,7 @@ s command and control functions. The interfaces between a VM and SCP are relati \par \tab int32 }{\b\f1 sim_emax}{\f1 \tab \tab maximum number of words in an instruction \par \tab DEVICE *}{\b\f1 sim_devices[]}{\f1 \tab table of pointers to simulated devices, NULL terminated \par \tab char *}{\b\f1 sim_stop_messages[]}{\f1 \tab table of pointers to error messages -\par \tab t_stat }{\b\f1 sim_load}{\f1 (FILE *fref)\tab binary loader subroutine +\par \tab t_stat }{\b\f1 sim_load}{\f1 (\'85)\tab \tab binary loader subroutine \par \tab t_stat }{\b\f1 sim_inst}{\f1 (void)\tab \tab instruction execution subroutine \par \tab t_stat }{\b\f1 parse_sym}{\f1 (\'85)\tab \tab symbolic instruction parse subroutine (optional) \par \tab t_stat }{\b\f1 fprint_sym}{\f1 (\'85)\tab \tab symbolic instruction print subroutine (optional) @@ -120,16 +124,16 @@ s command and control functions. The interfaces between a VM and SCP are relati \par There is no required organization for VM code. The following convention has been used so far. Let name be the }{\i\f1 name}{\f1 of the real system (i1401 for the IBM 1401; pdp1 for the PDP-1; pdp18b for the other 18-bit PDP\rquote s; pdp8 for the PDP-8; pdp11 for the PDP11; nova for Nova; hp2100 for the HP 21XX; id4 for the Interdata 4): \par -\par {\pntext\pard\plain\f3\fs20\cgrid \loch\af3\dbch\af0\hich\f3 \'b7\tab}}\pard \fi-360\li720\widctlpar\jclisttab\tx720{\*\pn \pnlvlblt\ilvl0\ls2\pnrnot0\pnf3\pnstart1\pnindent720\pnhang{\pntxtb \'b7}}\ls2\adjustright {\i\f1 name}{\f1 .h contains definition -s for the particular simulator +\par {\pntext\pard\plain\f3\fs20\cgrid \loch\af3\dbch\af0\hich\f3 \'b7\tab}}\pard \fi-360\li720\widctlpar\jclisttab\tx720{\*\pn \pnlvlblt\ilvl0\ls2\pnrnot0\pnf3\pnstart1\pnindent720\pnhang{\pntxtb \'b7}}\ls2\adjustright {\i\f1 name}{\f1 +.h contains definitions for the particular simulator \par {\pntext\pard\plain\f3\fs20\cgrid \loch\af3\dbch\af0\hich\f3 \'b7\tab}}\pard \fi-360\li720\widctlpar\jclisttab\tx720{\*\pn \pnlvlblt\ilvl0\ls2\pnrnot0\pnf3\pnstart1\pnindent720\pnhang{\pntxtb \'b7}}\ls2\adjustright {\i\f1 name}{\f1 _sys.c contains all the SCP interfaces except the instruction simulator \par {\pntext\pard\plain\f3\fs20\cgrid \loch\af3\dbch\af0\hich\f3 \'b7\tab}}\pard \fi-360\li720\widctlpar\jclisttab\tx720{\*\pn \pnlvlblt\ilvl0\ls2\pnrnot0\pnf3\pnstart1\pnindent720\pnhang{\pntxtb \'b7}}\ls2\adjustright {\i\f1 name}{\f1 _cpu.c contains the instruction simulator and CPU data structures \par {\pntext\pard\plain\f3\fs20\cgrid \loch\af3\dbch\af0\hich\f3 \'b7\tab}}\pard \fi-360\li720\widctlpar\jclisttab\tx720{\*\pn \pnlvlblt\ilvl0\ls2\pnrnot0\pnf3\pnstart1\pnindent720\pnhang{\pntxtb \'b7}}\ls2\adjustright {\i\f1 name}{\f1 _stddev.c contains the peripherals which were standard with the real system. -\par {\pntext\pard\plain\f3\fs20\cgrid \loch\af3\dbch\af0\hich\f3 \'b7\tab}}\pard \fi-360\li720\widctlpar\jclisttab\tx720{\*\pn \pnlvlblt\ilvl0\ls2\pnrnot0\pnf3\pnstart1\pnindent720\pnhang{\pntxtb \'b7}}\ls2\adjustright {\i\f1 name}{\f1 -_lp.c contains the line printer. +\par {\pntext\pard\plain\f3\fs20\cgrid \loch\af3\dbch\af0\hich\f3 \'b7\tab}}\pard \fi-360\li720\widctlpar\jclisttab\tx720{\*\pn \pnlvlblt\ilvl0\ls2\pnrnot0\pnf3\pnstart1\pnindent720\pnhang{\pntxtb \'b7}}\ls2\adjustright {\i\f1 name}{\f1 _lp.c contains the +line printer. \par {\pntext\pard\plain\f3\fs20\cgrid \loch\af3\dbch\af0\hich\f3 \'b7\tab}}\pard \fi-360\li720\widctlpar\jclisttab\tx720{\*\pn \pnlvlblt\ilvl0\ls2\pnrnot0\pnf3\pnstart1\pnindent720\pnhang{\pntxtb \'b7}}\ls2\adjustright {\i\f1 name}{\f1 _mt.c contains the mag tape controller and drives, etc. \par }\pard \fi1440\widctlpar\adjustright {\f1 @@ -151,38 +155,38 @@ _mt.c contains the mag tape controller and drives, etc. \par \par {\listtext\pard\plain\f1\fs20\cgrid \hich\af1\dbch\af0\loch\f1 3.1.1\tab}}\pard \fi-720\li720\widctlpar\jclisttab\tx720\ls1\ilvl2\adjustright {\f1 Time Base \par }\pard \widctlpar\adjustright {\f1 -\par In order to simulate asynchronous events, such as I/O completion, the VM must define and keep a time base. This can be accurate (for example, nanoseconds of executi -on) or arbitrary (for example, number of instructions executed), but it must be consistently used throughout the VM. All existing VM\rquote s count time in instructions. +\par In order to simulate asynchronous events, such as I/O completion, the VM must define and keep a time base. T +his can be accurate (for example, nanoseconds of execution) or arbitrary (for example, number of instructions executed), but it must be consistently used throughout the VM. All existing VM\rquote s count time in instructions. \par \par The CPU is responsible for counting down the event counter }{\b\f1 sim_interval}{\f1 and calling the asynchronous event controller }{\b\f1 sim_process_event}{\f1 . The record keeping for timing is done by SCP. \par \par {\listtext\pard\plain\f1\fs20\cgrid \hich\af1\dbch\af0\loch\f1 3.1.2\tab}}\pard \fi-720\li720\widctlpar\jclisttab\tx720\ls1\ilvl2\adjustright {\f1 Memory Organization \par }\pard \widctlpar\adjustright {\f1 -\par The criterion for memory layout is very simple: use the SIMH data type that is as large as (or if necessary, larger than), the word length of - the real machine. Note that the criterion is word length, not addressability: the PDP-11 has byte addressable memory, but it is a 16-bit machine, and its memory is defined as unsigned int16 M[]. It may seem tempting to define memory as a union of int8 -and int16 data types, but this would make the resulting VM endian-dependent. Instead, the VM should be based on the underlying word size of the real machine, and byte manipulation should be done explicitly. Examples: +\par The crit +erion for memory layout is very simple: use the SIMH data type that is as large as (or if necessary, larger than), the word length of the real machine. Note that the criterion is word length, not addressability: the PDP-11 has byte addressable memory, bu +t it is a 16-bit machine, and its memory is defined as uint16 M[]. It may seem tempting to define memory as a union of int8 and int16 data types, but this would make the resulting VM endian-dependent. Instead, the VM should be based on the underly +ing word size of the real machine, and byte manipulation should be done explicitly. Examples: \par \par \tab Simulator\tab \tab memory size\tab \tab memory declaration \par -\par \tab IBM 1401\tab \tab 6-bit\tab \tab \tab int8 -\par \tab PDP-8\tab \tab \tab 12-bit\tab \tab \tab int16 -\par \tab PDP-11, Nova\tab \tab 16-bit\tab \tab \tab int16 -\par \tab PDP-10\tab \tab \tab 36-bit\tab \tab \tab int64 +\par \tab IBM 1401\tab \tab 6-bit\tab \tab \tab unsigned int8 +\par \tab PDP-8\tab \tab \tab 12-bit\tab \tab \tab unsigned int16 +\par \tab PDP-11, Nova\tab \tab 16-bit\tab \tab \tab unsigned int16 +\par \tab PDP-10\tab \tab \tab 36-bit\tab \tab \tab unsigned int64 \par \par {\listtext\pard\plain\f1\fs20\cgrid \hich\af1\dbch\af0\loch\f1 3.1.3\tab}}\pard \fi-720\li720\widctlpar\jclisttab\tx720\ls1\ilvl2\adjustright {\f1 Interrupt Organization \par }\pard \widctlpar\adjustright {\f1 -\par The design of the VM\rquote s interrupt structure is a complex interaction between efficiency and fidelity to the hardware. If the VM\rquote -s interrupt structure is too abstract, interrupt driven software may not run. On the other hand, if it follows the hardware too literally, it may significantly reduce simulation speed. One rule I can offer is to minimize the fetch-phase cost of i -nterrupts, even if this complicates the (much less frequent) evaluation of the interrupt system following an I/O operation. Another is not to over-generalize; even if the real hardware could support 64 or 256 interrupting devices, the simulators will be -running much smaller configurations. I\rquote ll start with a simple interrupt structure and then offer suggestions for generalization. +\par The design of the VM\rquote s interrupt structure is a complex interaction between efficiency and fidelity to the hardware. If the VM\rquote s interrupt structure is too abstract, interrupt driven software may not +run. On the other hand, if it follows the hardware too literally, it may significantly reduce simulation speed. One rule I can offer is to minimize the fetch-phase cost of interrupts, even if this complicates the (much less frequent) evaluation of the i +nterrupt system following an I/O operation or asynchronous event. Another is not to over-generalize; even if the real hardware could support 64 or 256 interrupting devices, the simulators will be running much smaller configurations. I\rquote +ll start with a simple interrupt structure and then offer suggestions for generalization. \par -\par In the simplest structure, interrupt requests correspond to device flags and are kept in an interrupt request variable, with o -ne flag per bit. The fetch-phase evaluation of interrupts consists of two steps: are interrupts enabled, and is there an interrupt outstanding? If all the interrupt requests are kept as single-bit flags in a variable, the fetch-phase test is very fast: - +\par In the simplest structure, interrupt requests correspond to device flags and are kept in an interrupt request variable, with one flag per bit. The fetch-phase evaluation of interrupts +consists of two steps: are interrupts enabled, and is there an interrupt outstanding? If all the interrupt requests are kept as single-bit flags in a variable, the fetch-phase test is very fast: \par \par \tab if (int_enable && int_requests) \{ \'85process interrupt\'85 \} \par -\par Indeed, if the interrupt enable flag is not visible state, it can be made the highest bit in the interrupt request variable, and the two tests combined: +\par Indeed, the interrupt enable flag can be made the highest bit in the interrupt request variable, and the two tests combined: \par \par \tab if (int_requests > INT_ENABLE) \{ \'85process interrupt\'85 \} \par @@ -191,56 +195,54 @@ ne flag per bit. The fetch-phase evaluation of interrupts consists of two steps \par \tab set: \tab int_requests = int_requests | DEVICE_FLAG; \par \tab clear:\tab int_requests = int_requests & ~DEVICE_FLAG; \par -\par At a slightly higher complexity, interrupt - requests do not correspond directly to device flags but are based on masking the device flags with an enable (or disable) mask. There are now three parallel variables: interrupt requests, device flags, and interrupt enable mask. The fetch-phase test do -es not change; however, the evaluation of whether an interrupt is pending now requires an extra step: +\par At a slightly higher complexity, interrupt requests do +not correspond directly to device flags but are based on masking the device flags with an enable (or disable) mask. There are now three parallel variables: interrupt requests, device flags, and interrupt enable mask. The fetch-phase test does not change +; however, the evaluation of whether an interrupt is pending now requires an extra step: \par \par \tab enable:\tab int_requests = device_flags & int_enables; \par \tab disable:\tab int_requests = device_flags & ~int_disables; \par -\par If required for interrupt processing, the high -est priority interrupting device can be determined by scanning the interrupt request variable from high priority to low until a set bit is found. The bit position can then be back-mapped through a table to determine the address or interrupt vector of the - interrupting device. +\par If required for interrupt processing, the highest priority +interrupting device can be determined by scanning the interrupt request variable from high priority to low until a set bit is found. The bit position can then be back-mapped through a table to determine the address or interrupt vector of the interrupting + device. \par -\par At yet higher complexity, the interrupt system may be too complex or too large to evaluate during the fetch-phase. In this case, an interrupt pending flag is created, and it is evaluated by subroutine call whenever a change could occ -ur (start of execution, I/O instruction issued, device time out occurs). This makes fetch-phase evaluation simple and isolates interrupt evaluation to a common subroutine. +\par At yet higher complexity, the interrupt system may be too complex or too large to evaluate during the fetch-phase. In this case, an interrupt pending flag is created, and it is evaluated by subroutine call whenever a change could occur (start of +execution, I/O instruction issued, device time out occurs). This makes fetch-phase evaluation simple and isolates interrupt evaluation to a common subroutine. \par \par {\listtext\pard\plain\f1\fs20\cgrid \hich\af1\dbch\af0\loch\f1 3.1.4\tab}}\pard \fi-720\li720\widctlpar\jclisttab\tx720\ls1\ilvl2\adjustright {\f1 I/O Dispatching \par }\pard \widctlpar\adjustright {\f1 \par I/O dispatching consists of four steps: \par -\par {\pntext\pard\plain\f3\fs20\cgrid \loch\af3\dbch\af0\hich\f3 \'b7\tab}}\pard \fi-360\li720\widctlpar\jclisttab\tx720{\*\pn \pnlvlblt\ilvl0\ls14\pnrnot0\pnf3\pnstart1\pnindent720\pnhang{\pntxtb \'b7}}\ls14\adjustright {\f1 Identify the I/O command - and analyze for the device address. +\par {\pntext\pard\plain\f3\fs20\cgrid \loch\af3\dbch\af0\hich\f3 \'b7\tab}}\pard \fi-360\li720\widctlpar\jclisttab\tx720{\*\pn \pnlvlblt\ilvl0\ls14\pnrnot0\pnf3\pnstart1\pnindent720\pnhang{\pntxtb \'b7}}\ls14\adjustright {\f1 Identify the I/O command and + analyze for the device address. \par {\pntext\pard\plain\f3\fs20\cgrid \loch\af3\dbch\af0\hich\f3 \'b7\tab}}\pard \fi-360\li720\widctlpar\jclisttab\tx720{\*\pn \pnlvlblt\ilvl0\ls14\pnrnot0\pnf3\pnstart1\pnindent720\pnhang{\pntxtb \'b7}}\ls14\adjustright {\f1 Locate the selected device. \par {\pntext\pard\plain\f3\fs20\cgrid \loch\af3\dbch\af0\hich\f3 \'b7\tab}}\pard \fi-360\li720\widctlpar\jclisttab\tx720{\*\pn \pnlvlblt\ilvl0\ls14\pnrnot0\pnf3\pnstart1\pnindent720\pnhang{\pntxtb \'b7}}\ls14\adjustright {\f1 Break down the I/O command into standard fields. \par {\pntext\pard\plain\f3\fs20\cgrid \loch\af3\dbch\af0\hich\f3 \'b7\tab}}\pard \fi-360\li720\widctlpar\jclisttab\tx720{\*\pn \pnlvlblt\ilvl0\ls14\pnrnot0\pnf3\pnstart1\pnindent720\pnhang{\pntxtb \'b7}}\ls14\adjustright {\f1 Call the device processor. \par }\pard \widctlpar\adjustright {\f1 -\par Analyzing an I/O command is usually easy. Most systems have one or more explicit I/O instructions containing an I -/O command and a device address. Memory mapped I/O is more complicated; the identification of a reference to I/O space becomes part of memory addressing. This usually requires centralizing memory reads and writes into subroutines, rather than as inline -code. +\par Analyzing an I/O command is usually easy. Most systems have one or more explicit I/O instructions containing + an I/O command and a device address. Memory mapped I/O is more complicated; the identification of a reference to I/O space becomes part of memory addressing. This usually requires centralizing memory reads and writes into subroutines, rather than as in +line code. \par -\par Once an I/O command has been analyzed, the CPU must locate the device subroutine. The simplest way is a large switch statement with hardwired subroutine calls. Slightly more modular is to call through a dispatch table, with NULL entries representin -g non-existant devices. Before calling the device routine, the CPU usually breaks down the I/O command into standard fields. This simplifies writing the peripheral simulator. +\par Once an I/O command has been analyzed, the CPU must locate the device subroutine. The simplest way is a large switch statement with hardwired subroutine calls. Slightly more modular is to call through a dispatch table, with NULL +entries representing non-existent devices. Before calling the device routine, the CPU usually breaks down the I/O command into standard fields. This simplifies writing the peripheral simulator. \par \par {\listtext\pard\plain\f1\fs20\cgrid \hich\af1\dbch\af0\loch\f1 3.1.5\tab}}\pard \fi-720\li720\widctlpar\jclisttab\tx720\ls1\ilvl2\adjustright {\f1 Instruction Execution \par }\pard \widctlpar\adjustright {\f1 \par Instruction execution is the responsibility of VM subroutine }{\b\f1 sim_instr}{\f1 . It is called from SCP as a result of a RUN, GO, CONT, or BOOT command. It begins executing instructions at the current PC (}{\b\f1 sim_PC}{\f1 points to its register description block) and continues until halted by an error or an external event. \par -\par Whe -n called, the CPU needs to account for any state changes that the user made. For example, it may need to re-evaluate whether an interrupt is pending, or restore frequently used state to local register variables for efficiency. The actual instruction fet -ch and execute cycle is usually structured as a loop controlled by an error variable, e.g., +\par When called, the CPU needs to account for any state changes that the user made. For example, it may need to re-evaluate whether an interrupt is pending, or restore frequently used state to local register variables for efficiency. Th +e actual instruction fetch and execute cycle is usually structured as a loop controlled by an error variable, e.g., \par \par \tab reason = 0; \par \tab do \{ \'85 \} while (reason == 0);\tab or\tab while (reason == 0) \{ \'85 \} \par \par Within this loop, the usual order of events is: \par -\par {\pntext\pard\plain\f3\fs20\cgrid \loch\af3\dbch\af0\hich\f3 \'b7\tab}}\pard \fi-360\li720\widctlpar\jclisttab\tx720{\*\pn \pnlvlblt\ilvl0\ls4\pnrnot0\pnf3\pnstart1\pnindent720\pnhang{\pntxtb \'b7}}\ls4\adjustright {\f1 -If the event timer sim_interval has reached zero, process any timed events. This is done by SCP subroutine sim_process_event (void). Because this is the polling mechanism for user-generated processor halts (^E), errors must be recognized immediately: - +\par {\pntext\pard\plain\f3\fs20\cgrid \loch\af3\dbch\af0\hich\f3 \'b7\tab}}\pard \fi-360\li720\widctlpar\jclisttab\tx720{\*\pn \pnlvlblt\ilvl0\ls4\pnrnot0\pnf3\pnstart1\pnindent720\pnhang{\pntxtb \'b7}}\ls4\adjustright {\f1 If the event timer }{\b\f1 +sim_interval}{\f1 has reached zero, process any timed events. This is done by SCP subroutine }{\b\f1 sim_process_event}{\f1 . Because this is the polling mechanism for user-generated processor halts (^E), errors must be recognized immediately: \par }\pard \widctlpar{\*\pn \pnlvlcont\ilvl0\ls0\pnrnot0\pndec }\adjustright {\f1 \par }\pard \li1440\widctlpar{\*\pn \pnlvlcont\ilvl0\ls0\pnrnot0\pndec }\adjustright {\f1 if (sim_interval <= 0) \{ \par }\pard \fi720\li1440\widctlpar{\*\pn \pnlvlcont\ilvl0\ls0\pnrnot0\pndec }\adjustright {\f1 if (reason = sim_process_event ()) break; \} @@ -267,22 +269,22 @@ The VM should provide some debugging aids. The existing CPU\rquote s all provid \par }\pard \widctlpar\adjustright {\f1 \par {\listtext\pard\plain\f1\fs20\cgrid \hich\af1\dbch\af0\loch\f1 3.2\tab}}\pard \fi-360\li360\widctlpar\jclisttab\tx360\ls1\ilvl1\adjustright {\f1 Peripheral Device Organization \par }\pard \widctlpar\adjustright {\f1 -\par The basic elements of a VM are devices, each corresponding roughly to a real chunk of hardware. A device cons -ists of register-based state and one or more units. Thus a multi-drive disk subsystem is a single device (representing the hardware of the real controller) and one or more units (each representing a single disk drive). Sometimes the device and its unit -are the same entity as, for example, in the case of a paper tape reader. However, a single physical hardware device, such as the console, may be broken up for convenience into separate input and output devices. +\par The basic elements of a VM are devices, ea +ch corresponding roughly to a real chunk of hardware. A device consists of register-based state and one or more units. Thus, a multi-drive disk subsystem is a single device (representing the hardware of the real controller) and one or more units (each r +epresenting a single disk drive). Sometimes the device and its unit are the same entity as, for example, in the case of a paper tape reader. However, a single physical device, such as the console, may be broken up for convenience into separate in +put and output devices. \par -\par In general, units correspond to individual s -ources of input or output (one tape transport, one A-to-D channel). Units are the basic medium for both device timing and device I/O. Except for the console, all I/O devices are simulated as host-resident files. SCP allows the user to make an explicit -association between a host-resident file and a simulated hardware entity. +\par In general, units correspond to individual sources of input or output (one tape transport, one A-to-D channel). Units are the basic medium for both device timing and device I/O. Except for the console, all I/O devices are simulat +ed as host-resident files. SCP allows the user to make an explicit association between a host-resident file and a simulated hardware entity. \par \par Both devices and units have state. Devices operate on }{\i\f1 registers}{\f1 , which contain information about the state of the device, and indirectly, about the state of the units. Units operate on }{\i\f1 data sets}{\f1 -, which may be thought of as individual instances of input or output, such as a disk pack or a punched paper tape. In a typical multi-unit device, all units are the same, and the device performs similar operations on all of them, depending o -n which one has been selected by the program being simulated. Schematically: +, which may be thought of as individual instances of input or output, such as a disk pack or a punched paper tape. In a typical multi-unit device, all units are the same, a +nd the device performs similar operations on all of them, depending on which one has been selected by the program being simulated. \par \par (Note: SIMH, like MIMIC, restricts registers to devices. This requires replicated registers, for example, disk drive current state, to have unique names in the device name space.) \par -\par For each structural level, SIMH defines, and the VM must supply, a corresponding data structure. }{\b\f1 device}{\f1 structures correspond to devices, }{\b\f1 reg}{\f1 structures to registers, and }{\b\f1 unit}{\f1 - structures to units. These structures are described in detail in section 3. +\par For each structural level, SIMH defines, and the VM must supply, a corresponding data structure. }{\b\f1 device}{\f1 structures correspond to devices, }{\b\f1 reg}{\f1 structures to registers, and }{\b\f1 unit}{\f1 structures to units. + These structures are described in detail in section 4. \par \par The primary functions of a peripheral are: \par @@ -291,16 +293,15 @@ n which one has been selected by the program being simulated. Schematically: \par {\pntext\pard\plain\f3\fs20\cgrid \loch\af3\dbch\af0\hich\f3 \'b7\tab}}\pard \fi-360\li720\widctlpar\jclisttab\tx720{\*\pn \pnlvlblt\ilvl0\ls6\pnrnot0\pnf3\pnstart1\pnindent720\pnhang{\pntxtb \'b7}}\ls6\adjustright {\f1 device timing \par {\pntext\pard\plain\f3\fs20\cgrid \loch\af3\dbch\af0\hich\f3 \'b7\tab}}\pard \fi-360\li720\widctlpar\jclisttab\tx720{\*\pn \pnlvlblt\ilvl0\ls6\pnrnot0\pnf3\pnstart1\pnindent720\pnhang{\pntxtb \'b7}}\ls6\adjustright {\f1 data transmission. \par }\pard \widctlpar\adjustright {\f1 -\par Command decoding is fairly obvious. At least one section of the peripheral code module will be devoted to processing directives issued by the -CPU. Typically, the command decoder will be responsible for register and flag manipulation, and for issuing or canceling I/O requests. The former is easy, but the later requires a thorough understanding of device timing. +\par Command decoding is fairly obvious. At least one section of the peripheral code +module will be devoted to processing directives issued by the CPU. Typically, the command decoder will be responsible for register and flag manipulation, and for issuing or canceling I/O requests. The former is easy, but the later requires a thorough un +derstanding of device timing. \par \par {\listtext\pard\plain\f1\fs20\cgrid \hich\af1\dbch\af0\loch\f1 3.2.1\tab}}\pard \fi-720\li720\widctlpar\jclisttab\tx720\ls1\ilvl2\adjustright {\f1 Device Timing \par }\pard \widctlpar\adjustright {\f1 -\par The principal pro -blem in I/O device simulation is imitating asynchronous operations in a sequential simulation environment. Fortunately, the timing characteristics of most I/O devices do not vary with external circumstances. The distinction between devices whose timing -i -s externally generated (e.g., console keyboard) and those whose timing is externally generated (disk, paper tape reader) is crucial. With an externally timed device, there is no way to know when an in-progress operation will begin or end; with an interna -lly timed device, given the time when an operation starts, the end time can be calculated. +\par The principal problem in I/O device simulation is imitating asynchronous operations in a sequential simulation environment. Fortuna +tely, the timing characteristics of most I/O devices do not vary with external circumstances. The distinction between devices whose timing is externally generated (e.g., console keyboard) and those whose timing is externally generated (disk, paper tape r +eader) is crucial. With an externally timed device, there is no way to know when an in-progress operation will begin or end; with an internally timed device, given the time when an operation starts, the end time can be calculated. \par \par For an internally timed device, the elapsed time between the start and conclusion of an operation is called the wait time. Some typical internally timed devices and their wait times include: \par @@ -317,13 +318,13 @@ s poll for keyboard input, thus converting the externally timed keyboard to a ps \par SCP provides the supporting routines for device timing. SCP maintains a list of devices (called }{\i\f1 active devices}{\f1 ) which are in the process of timing out. It also provides routines for querying or manipulating this list (called the }{\i\f1 active queue}{\f1 ). Lastly, it provides a routine for checking for timed-out units and executing a VM-specified action when a time-out occurs. \par -\par Device timing is done with the UNIT structure, described in section 3. To set up a timed operation, the peripheral calculates a waiting period for a unit and places that unit on the active queue. The CPU counts down the waiting period. When the wai -ting period has expired, sim_process_event removes the unit from the active queue and calls a device subroutine. A device may also cancel an outstanding timed operation and query the state of the queue. The timing subroutines are: +\par Device timing is done with the UNIT structure, described in section 3. To set up a timed operation, the perip +heral calculates a waiting period for a unit and places that unit on the active queue. The CPU counts down the waiting period. When the waiting period has expired, }{\b\f1 sim_process_event}{\f1 + removes the unit from the active queue and calls a device subroutine. A device may also cancel an outstanding timed operation and query the state of the queue. The timing subroutines are: \par \par {\pntext\pard\plain\f3\fs20\cgrid \loch\af3\dbch\af0\hich\f3 \'b7\tab}}\pard \fi-360\li720\widctlpar\jclisttab\tx720{\*\pn \pnlvlblt\ilvl0\ls7\pnrnot0\pnf3\pnstart1\pnindent720\pnhang{\pntxtb \'b7}}\ls7\adjustright {\f1 t_stat }{\b\f1 sim_activate}{\f1 - (U -NIT *uptr, int32 wait). This routine places the specified unit on the active queue with the specified waiting period. A waiting period of 0 is legal; negative waits cause an error. If the unit is already active, the active queue is not changed, and no -error occurs. + (UNIT *uptr, int32 wait). This routine places the specified unit on the active queue with the specified waiting p +eriod. A waiting period of 0 is legal; negative waits cause an error. If the unit is already active, the active queue is not changed, and no error occurs. \par }\pard \widctlpar{\*\pn \pnlvlcont\ilvl0\ls0\pnrnot0\pndec }\adjustright {\f1 \par {\pntext\pard\plain\f3\fs20\cgrid \loch\af3\dbch\af0\hich\f3 \'b7\tab}}\pard \fi-360\li720\widctlpar\jclisttab\tx720{\*\pn \pnlvlblt\ilvl0\ls7\pnrnot0\pnf3\pnstart1\pnindent720\pnhang{\pntxtb \'b7}}\ls7\adjustright {\f1 t_stat }{\b\f1 sim_cancel}{\f1 (UNIT *uptr). This routine removes the specified unit from the active queue. If the unit is not on the queue, no error occurs. @@ -342,8 +343,8 @@ error occurs. \par }\pard \widctlpar\adjustright {\f1 \par {\listtext\pard\plain\f1\fs20\cgrid \hich\af1\dbch\af0\loch\f1 3.2.2\tab}}\pard \fi-720\li720\widctlpar\jclisttab\tx720\ls1\ilvl2\adjustright {\f1 Data I/O \par }\pard \widctlpar\adjustright {\f1 -\par For most devices, timing is half the battle (for clocks it is the entire war); the other half is I/O. Except for the console, all I/O devices are simulated as files on the host file system in little-endian format. - SCP provides facilities for associating files with units (ATTACH command) and for reading and writing data from and to devices in a endian- and size-independent way. +\par For most devices, timing is half the battle (for clocks it is the entire war); the other half is I/O. Except for the console, all I/O devices are simulated as files on the host file system in little-endian format. SCP provides facilities for associating + files with units (ATTACH command) and for reading and writing data from and to devices in a endian- and size-independent way. \par \par For most devices, the VM designer does not have to be concerned about the formatting of simulated device files. I/O occurs in 1, 2, or 4 byte quantities; SCP automatically chooses the correct data size and corrects for byte ordering. Specific issues: @@ -351,33 +352,34 @@ error occurs. \par {\pntext\pard\plain\f3\fs20\cgrid \loch\af3\dbch\af0\hich\f3 \'b7\tab}}\pard \fi-360\li720\widctlpar\jclisttab\tx720{\*\pn \pnlvlblt\ilvl0\ls8\pnrnot0\pnf3\pnstart1\pnindent720\pnhang{\pntxtb \'b7}}\ls8\adjustright {\f1 Line printers should write data as 7-bit ASCII, with newlines replacing carriage-return/line-feed sequences. \par }\pard \widctlpar{\*\pn \pnlvlcont\ilvl0\ls0\pnrnot0\pndec }\adjustright {\f1 -\par {\pntext\pard\plain\f3\fs20\cgrid \loch\af3\dbch\af0\hich\f3 \'b7\tab}}\pard \fi-360\li720\widctlpar\jclisttab\tx720{\*\pn \pnlvlblt\ilvl0\ls8\pnrnot0\pnf3\pnstart1\pnindent720\pnhang{\pntxtb \'b7}}\ls8\adjustright {\f1 -Disks should be viewed as linear data sets, from sector 0 of surface 0 of cylinder 0 to the last sector on the disk. This allows easy transcription of real disks to files usable by the simulator. +\par {\pntext\pard\plain\f3\fs20\cgrid \loch\af3\dbch\af0\hich\f3 \'b7\tab}}\pard \fi-360\li720\widctlpar\jclisttab\tx720{\*\pn \pnlvlblt\ilvl0\ls8\pnrnot0\pnf3\pnstart1\pnindent720\pnhang{\pntxtb \'b7}}\ls8\adjustright {\f1 Disks should be + viewed as linear data sets, from sector 0 of surface 0 of cylinder 0 to the last sector on the disk. This allows easy transcription of real disks to files usable by the simulator. \par }\pard \widctlpar{\*\pn \pnlvlcont\ilvl0\ls0\pnrnot0\pndec }\adjustright {\f1 \par {\pntext\pard\plain\f3\fs20\cgrid \loch\af3\dbch\af0\hich\f3 \'b7\tab}}\pard \fi-360\li720\widctlpar\jclisttab\tx720{\*\pn \pnlvlblt\ilvl0\ls8\pnrnot0\pnf3\pnstart1\pnindent720\pnhang{\pntxtb \'b7}}\ls8\adjustright {\f1 -Magtapes, by convention, use a record -based format. Each record consists of a leading 32-bit record length, the record data (padded with a byte of 0 if the record length is odd), and a trailing 32-bit record length. File marks are recorded as one record length of 0. +Magtapes, by convention, use a record based format. Each record consi +sts of a leading 32-bit record length, the record data (padded with a byte of 0 if the record length is odd), and a trailing 32-bit record length. File marks are recorded as one record length of 0. \par }\pard \widctlpar{\*\pn \pnlvlcont\ilvl0\ls0\pnrnot0\pndec }\adjustright {\f1 -\par {\pntext\pard\plain\f3\fs20\cgrid \loch\af3\dbch\af0\hich\f3 \'b7\tab}}\pard \fi-360\li720\widctlpar\jclisttab\tx720{\*\pn \pnlvlblt\ilvl0\ls8\pnrnot0\pnf3\pnstart1\pnindent720\pnhang{\pntxtb \'b7}}\ls8\adjustright {\f1 Cards have 12 bits of da -ta per column, but the data is most conveniently viewed as (ASCII) characters. Existing card reader simulators do not support binary operation. +\par {\pntext\pard\plain\f3\fs20\cgrid \loch\af3\dbch\af0\hich\f3 \'b7\tab}}\pard \fi-360\li720\widctlpar\jclisttab\tx720{\*\pn \pnlvlblt\ilvl0\ls8\pnrnot0\pnf3\pnstart1\pnindent720\pnhang{\pntxtb \'b7}}\ls8\adjustright {\f1 +Cards have 12 bits of data per column, but the data is most conveniently viewed as (ASCII) characters. Existing card reader simulators do not support binary operation. \par }\pard \widctlpar\adjustright {\f1 -\par Data I/O varies between fixed and variable capacity devices, and between buffered and non-buffered devices. A - fixed capacity device differs from a variable capacity device in that the file attached to the former has a maximum size, while the file attached to the latter may expand indefinitely. A buffered device differs from a non-buffered device in that the for -mer buffers its data set in host memory, while the latter maintains it as a file. Most variable capacity devices (such as the paper tape reader and punch) are sequential; all buffered devices are fixed capacity. -\par -\par 2.3.2.1 Reading and Writing Data +\par Data I/O varies between fixed and variable capacity devices, and between buffered and non-buffered devices. A fixed capacity device differ +s from a variable capacity device in that the file attached to the former has a maximum size, while the file attached to the latter may expand indefinitely. A buffered device differs from a non-buffered device in that the former buffers its data set in h +ost memory, while the latter maintains it as a file. Most variable capacity devices (such as the paper tape reader and punch) are sequential; all buffered devices are fixed capacity. \par +\par {\listtext\pard\plain\f1\fs20\cgrid \hich\af1\dbch\af0\loch\f1 3.2.2.1\tab}}\pard \fi-720\li720\widctlpar\jclisttab\tx720\ls1\ilvl3\adjustright {\f1 Reading and Writing Data +\par }\pard \widctlpar\adjustright {\f1 \par The ATTACH command creates an association between a host file and an I/O unit. For non-buffered devices, ATTACH stores the file pointer for the host file in the }{\b\f1 fileref}{\f1 field of the UNIT structure. For buffered devices, ATTACH reads the entire host file into an allocated buffer pointed to by the }{\b\f1 filebuf }{\f1 field of the UNIT structure. \par -\par For non-buffered devices, I/O is done with standard C subroutines plus the SCP routines }{\b\f1 fxread}{\f1 and }{\b\f1 fxwrite}{\f1 . }{\b\f1 fxread}{\f1 and }{\b\f1 fxwrite}{\f1 are identical in calling sequence and function to fread -and fwrite, respectively, but will correct for endian dependencies. For buffered devices, I/O is done by copying data to or from the allocated buffer. The device code must maintain the number (+1) of the highest address modified in the }{\b\f1 hwmark}{ -\f1 field of the UNIT structure. For both the non-buffered and buffered cases, the device must perform all address calculations and positioning operations. +\par For non-buffered devices, I/O is done with standard C subroutines plus the SCP routines }{\b\f1 fxread}{\f1 and }{\b\f1 fxwrite}{\f1 . }{\b\f1 fxread}{\f1 and }{\b\f1 fxwrite}{\f1 + are identical in calling sequence and function to fread and fwrite, respectively, but + will correct for endian dependencies. For buffered devices, I/O is done by copying data to or from the allocated buffer. The device code must maintain the number (+1) of the highest address modified in the }{\b\f1 hwmark}{\f1 + field of the UNIT structure. For both the non-buffered and buffered cases, the device must perform all address calculations and positioning operations. \par \par The DETACH command breaks the association between a host file and an I/O unit. For buffered devices, DETACH writes the allocated buffer back to the host file. \par -\par 2.3.2.2 Console I/O -\par +\par {\listtext\pard\plain\f1\fs20\cgrid \hich\af1\dbch\af0\loch\f1 3.2.2.2\tab}}\pard \fi-720\li720\widctlpar\jclisttab\tx720\ls1\ilvl3\adjustright {\f1 Console I/O +\par }\pard \widctlpar\adjustright {\f1 \par SCP provides two routines for console I/O. \par \par {\pntext\pard\plain\f3\fs20\cgrid \loch\af3\dbch\af0\hich\f3 \'b7\tab}}\pard \fi-360\li720\widctlpar\jclisttab\tx720{\*\pn \pnlvlblt\ilvl0\ls10\pnrnot0\pnf3\pnstart1\pnindent720\pnhang{\pntxtb \'b7}}\ls10\adjustright {\f1 t_stat }{\b\f1 sim_poll_char }{ @@ -386,12 +388,12 @@ and fwrite, respectively, but will correct for endian dependencies. For buffere \par {\pntext\pard\plain\f3\fs20\cgrid \loch\af3\dbch\af0\hich\f3 \'b7\tab}}\pard \fi-360\li720\widctlpar\jclisttab\tx720{\*\pn \pnlvlblt\ilvl0\ls10\pnrnot0\pnf3\pnstart1\pnindent720\pnhang{\pntxtb \'b7}}\ls10\adjustright {\f1 t_stat }{\b\f1 sim_putchar}{\f1 (int32 char). This routine types the specified ASCII character on the console. There are no errors. \par }\pard \widctlpar\adjustright {\f1 -\par {\listtext\pard\plain\f1\fs20\cgrid \hich\af1\dbch\af0\loch\f1 3.\tab}}\pard \fi-360\li360\widctlpar\jclisttab\tx360\ls13\adjustright {\f1 Data Structures +\par {\listtext\pard\plain\f1\fs20\cgrid \hich\af1\dbch\af0\loch\f1 4.\tab}}\pard \fi-360\li360\widctlpar\jclisttab\tx360\ls1\adjustright {\f1 Data Structures \par }\pard \widctlpar\adjustright {\f1 \par The devices, units, and registers which make up a VM are formally described through a set of data structures which interface the VM to the control portions of SCP. The devices themselves are pointed to by the device list array }{\b\f1 sim_devices[]}{\f1 . Within a device, both units and registers are allocated contiguously as arrays of structures. In addition, many devices allow the user to set or clear options via a modifications table. \par -\par {\listtext\pard\plain\b\f1\fs20\cgrid \hich\af1\dbch\af0\loch\f1 3.1\tab}}\pard \fi-360\li360\widctlpar\jclisttab\tx360\ls13\ilvl1\adjustright {\b\f1 device}{\f1 Structure +\par {\listtext\pard\plain\b\f1\fs20\cgrid \hich\af1\dbch\af0\loch\f1 4.1\tab}}\pard \fi-360\li360\widctlpar\jclisttab\tx360\ls1\ilvl1\adjustright {\b\f1 device}{\f1 Structure \par }\pard \widctlpar\adjustright {\f1 \par Devices are defined by the }{\b\f1 device}{\f1 structure (typedef }{\b\f1 DEVICE}{\f1 ), which has the following fields: \par @@ -433,10 +435,10 @@ and fwrite, respectively, but will correct for endian dependencies. For buffere \par }{\b\f1 attach}{\f1 \tab \tab address of special device attach routine, or NULL if none is required. \par }{\b\f1 detach}{\f1 \tab \tab address of special device detach routine, or NULL if none is required. \par }\pard \widctlpar\adjustright {\f1 -\par {\listtext\pard\plain\f1\fs20\cgrid \hich\af1\dbch\af0\loch\f1 3.1.1\tab}}\pard \fi-720\li720\widctlpar\jclisttab\tx720\ls13\ilvl2\adjustright {\f1 Examine and Deposit Routines +\par {\listtext\pard\plain\f1\fs20\cgrid \hich\af1\dbch\af0\loch\f1 4.1.1\tab}}\pard \fi-720\li720\widctlpar\jclisttab\tx720\ls1\ilvl2\adjustright {\f1 Examine and Deposit Routines \par }\pard \widctlpar\adjustright {\f1 -\par For devices which maintain their data sets as host files, SCP implements the examine and deposit data functions. However, devices which maintain their d -ata sets as private state (typically just the CPU) must supply special examine and deposit routines. The calling sequences are: +\par For devices which maintain their data sets as host files, SCP implements the examine and deposit data functions. However, devices which maintain their data sets as private state (typically just the CPU) must supply special examine and deposit routines. +The calling sequences are: \par \par }\pard \li720\widctlpar\adjustright {\f1 t_stat }{\i\f1 examine_routine}{\f1 (t_val *eval_array, t_addr addr, UNIT *uptr, int32 switches) \endash Copy }{\b\f1 sim_emax}{\f1 consecutive addresses for unit }{\i\f1 uptr}{\f1 , starting at }{\i\f1 addr}{ \f1 , into }{\i\f1 eval_array}{\f1 . The }{\i\f1 switch}{\f1 variable has bit set if the n\rquote th letter was specified as a switch to the examine command. @@ -444,7 +446,7 @@ ata sets as private state (typically just the CPU) must supply special examine a \par t_stat }{\i\f1 deposit_routine}{\f1 (t_val value, t_addr addr, UNIT *uptr, int32 switches) \endash Store the specified }{\i\f1 value}{\f1 in the specified }{\i\f1 addr}{\f1 for unit }{\i\f1 uptr}{\f1 . The }{\i\f1 switch}{\f1 variable is the same as for the examine routine. \par }\pard \widctlpar\adjustright {\f1 -\par {\listtext\pard\plain\f1\fs20\cgrid \hich\af1\dbch\af0\loch\f1 3.1.2\tab}}\pard \fi-720\li720\widctlpar\jclisttab\tx720\ls13\ilvl2\adjustright {\f1 Reset Routine +\par {\listtext\pard\plain\f1\fs20\cgrid \hich\af1\dbch\af0\loch\f1 4.1.2\tab}}\pard \fi-720\li720\widctlpar\jclisttab\tx720\ls1\ilvl2\adjustright {\f1 Reset Routine \par }\pard \widctlpar\adjustright {\f1 \par The reset routine implements the device reset function for the RESET, RUN, and BOOT commands. Its calling sequence is: \par @@ -452,15 +454,15 @@ ata sets as private state (typically just the CPU) must supply special examine a \par \par A typical reset routine clears all device flags and cancels any outstanding timing operations. \par -\par {\listtext\pard\plain\f1\fs20\cgrid \hich\af1\dbch\af0\loch\f1 3.1.3\tab}}\pard \fi-720\li720\widctlpar\jclisttab\tx720\ls13\ilvl2\adjustright {\f1 Boot Routine +\par {\listtext\pard\plain\f1\fs20\cgrid \hich\af1\dbch\af0\loch\f1 4.1.3\tab}}\pard \fi-720\li720\widctlpar\jclisttab\tx720\ls1\ilvl2\adjustright {\f1 Boot Routine \par }\pard \widctlpar\adjustright {\f1 \par If a device responds to a BOOT command, the boot routine implements the bootstrapping function. Its calling sequence is: \par -\par \tab t_stat boot_routine (int32 unit_number) \endash Bootstrap the specified unit. +\par \tab t_stat }{\i\f1 boot_routine}{\f1 (int32 unit_number) \endash Bootstrap the specified unit. \par \par A typical bootstrap routine copies a bootstrap loader into main memory and sets the PC to the starting address of the loader. SCP then starts simulation at the specified address. \par -\par {\listtext\pard\plain\f1\fs20\cgrid \hich\af1\dbch\af0\loch\f1 3.1.4\tab}}\pard \fi-720\li720\widctlpar\jclisttab\tx720\ls13\ilvl2\adjustright {\f1 Attach and Detach Routines +\par {\listtext\pard\plain\f1\fs20\cgrid \hich\af1\dbch\af0\loch\f1 4.1.4\tab}}\pard \fi-720\li720\widctlpar\jclisttab\tx720\ls1\ilvl2\adjustright {\f1 Attach and Detach Routines \par }\pard \widctlpar\adjustright {\f1 \par Normally, the ATTACH and DETACH commands are handled by SCP. However, devices which need to pre- or post-process these commands must supply special attach and detach routines. The calling sequences are: \par @@ -482,7 +484,7 @@ ata sets as private state (typically just the CPU) must supply special examine a \par \tab return detach_unit (uptr); \par \} \par }\pard \widctlpar\adjustright {\f1 -\par {\listtext\pard\plain\b\f1\fs20\cgrid \hich\af1\dbch\af0\loch\f1 3.2\tab}}\pard \fi-360\li360\widctlpar\jclisttab\tx360\ls13\ilvl1\adjustright {\b\f1 unit}{\f1 Structure +\par {\listtext\pard\plain\b\f1\fs20\cgrid \hich\af1\dbch\af0\loch\f1 4.2\tab}}\pard \fi-360\li360\widctlpar\jclisttab\tx360\ls1\ilvl1\adjustright {\b\f1 unit}{\f1 Structure \par }\pard \widctlpar\adjustright {\b\f1 \par }{\f1 Units are allocated as contiguous array. Each unit is defined with a }{\b\f1 unit}{\f1 structure (typedef }{\b\f1 UNIT}{\f1 ), which has the following fields: \par @@ -531,7 +533,7 @@ ata sets as private state (typically just the CPU) must supply special examine a \par \par defines the line printer as a sequential unit with a wait time of 500. \par -\par {\listtext\pard\plain\f1\fs20\cgrid \hich\af1\dbch\af0\loch\f1 3.2.1\tab}}\pard \fi-720\li720\widctlpar\jclisttab\tx720\ls13\ilvl2\adjustright {\f1 Unit Flags +\par {\listtext\pard\plain\f1\fs20\cgrid \hich\af1\dbch\af0\loch\f1 4.2.1\tab}}\pard \fi-720\li720\widctlpar\jclisttab\tx720\ls1\ilvl2\adjustright {\f1 Unit Flags \par }\pard \widctlpar\adjustright {\f1 \par The }{\b\f1 flags }{\f1 field contains indicators of current unit status. SIMH defines 11 flags: \par @@ -549,10 +551,11 @@ ata sets as private state (typically just the CPU) must supply special examine a \par UNIX_FIX\tab \tab the unit is fixed capacity. \par UNIT_BINK\tab \tab the unit measures \ldblquote K\rdblquote as 1024, rather than 1000. \par }\pard \widctlpar\adjustright {\f1 -\par Starting at bit position UNIT_V_UF, the remaining flags are device-specific. Device-specific flags are set and cleared with the SET and CLEAR commands, which reference the MTAB array (see below). De -vice-specific flags and UNIT_DIS are not automatically saved and restored; the device must supply a register covering these bits. +\par Starting at bit position UNIT_V_UF, the remaining flags are + device-specific. Device-specific flags are set and cleared with the SET and CLEAR commands, which reference the MTAB array (see below). Device-specific flags and UNIT_DIS are not automatically saved and restored; the device must supply a register cover +ing these bits. \par -\par {\listtext\pard\plain\f1\fs20\cgrid \hich\af1\dbch\af0\loch\f1 3.2.2\tab}}\pard \fi-720\li720\widctlpar\jclisttab\tx720\ls13\ilvl2\adjustright {\f1 Service Routine +\par {\listtext\pard\plain\f1\fs20\cgrid \hich\af1\dbch\af0\loch\f1 4.2.2\tab}}\pard \fi-720\li720\widctlpar\jclisttab\tx720\ls1\ilvl2\adjustright {\f1 Service Routine \par }\pard \widctlpar\adjustright {\f1 \par This routine is called by }{\b\f1 sim_process_event}{\f1 when a unit times out. Its calling sequence is: \par @@ -560,7 +563,7 @@ vice-specific flags and UNIT_DIS are not automatically saved and restored; the d \par }\pard \widctlpar\adjustright {\f1 \par The status returned by the service routine is passed by }{\b\f1 sim_process_event}{\f1 back to the CPU. \par -\par {\listtext\pard\plain\b\f1\fs20\cgrid \hich\af1\dbch\af0\loch\f1 3.3\tab}}\pard \fi-360\li360\widctlpar\jclisttab\tx360\ls13\ilvl1\adjustright {\b\f1 reg}{\f1 Structure +\par {\listtext\pard\plain\b\f1\fs20\cgrid \hich\af1\dbch\af0\loch\f1 4.3\tab}}\pard \fi-360\li360\widctlpar\jclisttab\tx360\ls1\ilvl1\adjustright {\b\f1 reg}{\f1 Structure \par }\pard \widctlpar\adjustright {\b\f1 \par }{\f1 Registers are allocated as contiguous array, with a NULL register at the end. Each register is defined with a }{\b\f1 reg}{\f1 structure (typedef }{\b\f1 REG}{\f1 ), which has the following fields: \par @@ -584,8 +587,8 @@ vice-specific flags and UNIT_DIS are not automatically saved and restored; the d \par }{\b\f1 depth\tab }{\f1 \tab size of data array (normally 1). \par }{\b\f1 flags}{\f1 \tab \tab flags and formatting information. \par }\pard \widctlpar\adjustright {\f1 -\par The }{\b\f1 depth}{\f1 field is only used with special \ldblquote arrayed registers\rdblquote , like the data buffer in the PDP floppy disk -controller. Arrayed registers cannot be examined or deposited, but all the values in the array will be saved and restored by SAVE and RESTORE. +\par The }{\b\f1 depth}{\f1 field is only used with special \ldblquote arrayed registers\rdblquote , like the data buffer in the PDP floppy disk controller. Arrayed registers cannot be examined or deposited, but all th +e values in the array will be saved and restored by SAVE and RESTORE. \par \par Macros }{\b\f1 ORDATA}{\f1 , }{\b\f1 DRDATA}{\f1 , and }{\b\f1 HRDATA}{\f1 define right-justified octal, decimal, and hexidecimal registers, respectively. They are invoked by: \par @@ -608,7 +611,7 @@ controller. Arrayed registers cannot be examined or deposited, but all the valu \par \tab REG lpt_reg = \{ \par \tab \tab \{ DRDATA\tab (POS, lpt_unit.pos, 31), PV_LFT \}, \'85 \} \par -\par {\listtext\pard\plain\f1\fs20\cgrid \hich\af1\dbch\af0\loch\f1 3.3.1\tab}}\pard \fi-720\li720\widctlpar\jclisttab\tx720\ls13\ilvl2\adjustright {\f1 Register Flags +\par {\listtext\pard\plain\f1\fs20\cgrid \hich\af1\dbch\af0\loch\f1 4.3.1\tab}}\pard \fi-720\li720\widctlpar\jclisttab\tx720\ls1\ilvl2\adjustright {\f1 Register Flags \par }\pard \widctlpar\adjustright {\f1 \par The }{\b\f1 flags }{\f1 field contains indicators that control register examination and deposit. \par @@ -622,7 +625,7 @@ controller. Arrayed registers cannot be examined or deposited, but all the valu \par REG_HRO\tab \tab register is read only and hidden. \par REG_NZ\tab \tab new register values must be non-zero. \par -\par {\listtext\pard\plain\b\f1\fs20\cgrid \hich\af1\dbch\af0\loch\f1 3.4\tab}}\pard \fi-360\li360\widctlpar\jclisttab\tx360\ls13\ilvl1\adjustright {\b\f1 mtab}{\f1 Structure +\par {\listtext\pard\plain\b\f1\fs20\cgrid \hich\af1\dbch\af0\loch\f1 4.4\tab}}\pard \fi-360\li360\widctlpar\jclisttab\tx360\ls1\ilvl1\adjustright {\b\f1 mtab}{\f1 Structure \par }\pard \widctlpar\adjustright {\b\f1 \par }{\f1 Device-specific SHOW and SET commands are processed using the modifications array, which is allocated as contiguous array, with a NULL at the end. Each possible modification is defined with a }{\b\f1 mtab}{\f1 structure (synonym }{\b\f1 MTAB}{\f1 ), which has the following fields: @@ -644,14 +647,14 @@ controller. Arrayed registers cannot be examined or deposited, but all the valu \par }{\b\f1 mstring}{\f1 \tab pointer to character string to be matched (SET, CLEAR) \par }{\b\f1 valid}{\f1 \tab address of validation routine, or NULL if none required \par }\pard \fi-1440\li1440\widctlpar\adjustright {\f1 -\par {\listtext\pard\plain\f1\fs20\cgrid \hich\af1\dbch\af0\loch\f1 3.4.1\tab}}\pard \fi-720\li720\widctlpar\jclisttab\tx720\ls13\ilvl2\adjustright {\f1 Validation Routine +\par {\listtext\pard\plain\f1\fs20\cgrid \hich\af1\dbch\af0\loch\f1 4.4.1\tab}}\pard \fi-720\li720\widctlpar\jclisttab\tx720\ls1\ilvl2\adjustright {\f1 Validation Routine \par }\pard \widctlpar\adjustright {\f1 \par The validation routine is called during SET processing to make sure that the proposed modification is valid. It can make other state changes required by the modification or initiate additional dialogs needed by the modifier. Its calling sequence is: \par \par }\pard \li720\widctlpar\adjustright {\f1 t_stat }{\i\f1 validation_routine}{\f1 (UNIT *uptr, int32 value) \endash test that }{\i\f1 uptr}{\f1 .}{\b\f1 flags}{\f1 can be set to }{\i\f1 value}{\f1 . \par }\pard \widctlpar\adjustright {\f1 -\par {\listtext\pard\plain\f1\fs20\cgrid \hich\af1\dbch\af0\loch\f1 3.5\tab}}\pard \fi-360\li360\widctlpar\jclisttab\tx360\ls13\ilvl1\adjustright {\f1 Other Data Structures +\par {\listtext\pard\plain\f1\fs20\cgrid \hich\af1\dbch\af0\loch\f1 4.5\tab}}\pard \fi-360\li360\widctlpar\jclisttab\tx360\ls1\ilvl1\adjustright {\f1 Other Data Structures \par }\pard \widctlpar\adjustright {\f1 \par char }{\b\f1 sim_name[]}{\f1 is a character array containing the VM name. \par @@ -664,15 +667,15 @@ controller. Arrayed registers cannot be examined or deposited, but all the valu \par char *}{\b\f1 sim_stop_messages[]}{\f1 is an array of pointers to character strings, corresponding to error status returns greater than zero. If }{\b\f1 sim_instr}{\f1 returns status code n > 0, then }{\b\f1 sim_stop_message[n]}{\f1 is printed by SCP. \par -\par {\listtext\pard\plain\f1\fs20\cgrid \hich\af1\dbch\af0\loch\f1 4.\tab}}\pard \fi-360\li360\widctlpar\jclisttab\tx360\ls13\adjustright {\f1 VM Provided Routines +\par {\listtext\pard\plain\f1\fs20\cgrid \hich\af1\dbch\af0\loch\f1 5.\tab}}\pard \fi-360\li360\widctlpar\jclisttab\tx360\ls1\adjustright {\f1 VM Provided Routines \par }\pard \widctlpar\adjustright {\f1 -\par {\listtext\pard\plain\f1\fs20\cgrid \hich\af1\dbch\af0\loch\f1 4.1\tab}}\pard \fi-360\li360\widctlpar\jclisttab\tx360\ls13\ilvl1\adjustright {\f1 Instruction Execution +\par {\listtext\pard\plain\f1\fs20\cgrid \hich\af1\dbch\af0\loch\f1 5.1\tab}}\pard \fi-360\li360\widctlpar\jclisttab\tx360\ls1\ilvl1\adjustright {\f1 Instruction Execution \par }\pard \widctlpar\adjustright {\f1 \par Instruction execution is performed by routine }{\b\f1 sim_instr}{\f1 . Its calling sequence is: \par \par t_stat }{\b\f1 sim_instr}{\f1 (void) \endash Execute from current PC until error or halt. \par -\par {\listtext\pard\plain\f1\fs20\cgrid \hich\af1\dbch\af0\loch\f1 4.2\tab}}\pard \fi-360\li360\widctlpar\jclisttab\tx360\ls13\ilvl1\adjustright {\f1 Binary Load and Dump +\par {\listtext\pard\plain\f1\fs20\cgrid \hich\af1\dbch\af0\loch\f1 5.2\tab}}\pard \fi-360\li360\widctlpar\jclisttab\tx360\ls1\ilvl1\adjustright {\f1 Binary Load and Dump \par }\pard \widctlpar\adjustright {\f1 \par If the VM responds to the LOAD (or DUMP) command, the loader (dumper) is implemented by routine }{\b\f1 sim_load}{\f1 . Its calling sequence is: \par @@ -681,7 +684,7 @@ controller. Arrayed registers cannot be examined or deposited, but all the valu \par }\pard \widctlpar\adjustright {\f1 \par If LOAD or DUMP is not implemented, }{\b\f1 sim_load}{\f1 should simply return SCPE_ARG. The LOAD and DUMP commands open and close the specified file for }{\b\f1 sim_load}{\f1 . \par -\par {\listtext\pard\plain\f1\fs20\cgrid \hich\af1\dbch\af0\loch\f1 4.3\tab}}\pard \fi-360\li360\widctlpar\jclisttab\tx360\ls13\ilvl1\adjustright {\f1 Symbolic Examination and Deposit +\par {\listtext\pard\plain\f1\fs20\cgrid \hich\af1\dbch\af0\loch\f1 5.3\tab}}\pard \fi-360\li360\widctlpar\jclisttab\tx360\ls1\ilvl1\adjustright {\f1 Symbolic Examination and Deposit \par }\pard \widctlpar\adjustright {\f1 \par If the VM provides symbolic examination and deposit of data, it must provide two routines, }{\b\f1 fprint_sym}{\f1 for output and }{\b\f1 parse_sym}{\f1 for input. Their calling sequences are: \par @@ -691,8 +694,8 @@ controller. Arrayed registers cannot be examined or deposited, but all the valu \par t_stat }{\b\f1 parse_sym}{\f1 (char *cptr, t_addr addr, UNIT *uptr, t_value *val, int32 switch) \endash Based on the }{\i\f1 switch}{\f1 variable, parse character string }{\i\f1 cptr}{\f1 for a symbolic value }{\i\f1 val}{\f1 at the specified }{ \i\f1 addr}{\f1 in unit }{\i\f1 uptr}{\f1 . \par }\pard \widctlpar\adjustright {\f1 -\par If symbolic processing is not implemented, or the output value or input string cannot be parsed, these routines should return SCPE_ARG. If the processing was successful and con -sumed more than a single word, then these routines should return extra number of words (not bytes) consumed as a }{\b\f1 negative}{\f1 +\par If symbolic processing is not implemented, or the output value or input string cannot be parsed, these routines should return SCPE_ARG. If the processing was successful and consume +d more than a single word, then these routines should return extra number of words (not bytes) consumed as a }{\b\f1 negative}{\f1 number. If the processing was successful and consumed a single word, then these routines should return SCPE_OK. For example, PDP-11 }{\b\f1 parse_sym}{\f1 would respond as follows to various inputs: \par \par \tab input\tab \tab \tab \tab return value diff --git a/simh_doc.txt b/simh_doc.txt index e133f4f2..a1c57ced 100644 --- a/simh_doc.txt +++ b/simh_doc.txt @@ -1,6 +1,6 @@ To: Users From: Bob Supnik -Subj: Simulator Usage, V2.5 +Subj: Simulator Usage, V2.5a Date: 1-Jan-01 COPYRIGHT NOTICE @@ -743,14 +743,14 @@ The magnetic tape controller implements these registers: Error handling is as follows: - error processed as + error processed as - not attached tape not ready + not attached tape not ready - end of file (read or space) end of physical tape - (write) ignored + end of file (read or space) end of physical tape + (write) ignored - OS I/O error report error and stop + OS I/O error report error and stop 4.7 Symbolic Display and Input @@ -1288,14 +1288,14 @@ The magnetic tape controller implements these registers: Error handling is as follows: - error processed as + error processed as - not attached tape not ready + not attached tape not ready - end of file (read or space) end of physical tape - (write) ignored + end of file (read or space) end of physical tape + (write) ignored - OS I/O error report error and stop + OS I/O error report error and stop 5.8 Symbolic Display and Input @@ -1371,7 +1371,9 @@ CPU Nova CPU with 32KW of memory - hardware multiply/divide PTR,PTP paper tape reader/punch TTI,TTO console terminal +TTI1,TTO1 second terminal LPT line printer +PLT plotter CLK real-time clock DK head-per-track disk controller DP moving head disk controller with four drives @@ -1406,9 +1408,9 @@ and the size of main memory. SET CPU 28K set memory size = 28K SET CPU 32K set memory size = 32K -(Nova 4 = optional multiply/divide, stack, byte, trap instructions) -(Nova 3 = optional multiply/divide, stack instructions) -(MDV = multiply/divide instructions) +(MDV = unsigned multiply/divide instructions) +(Nova 3 = unsigned multiply/divide, stack, trap instructions) +(Nova 4 = unsigned and signed multiply/divide, stack, byte, trap instructions) If memory size is being reduced, and the memory being truncated contains non-zero data, the simulator asks for confirmation. Data in the truncated @@ -1460,7 +1462,7 @@ The paper tape reader implements these registers: Error handling is as follows: - errpr STOP_IOE processed as + error STOP_IOE processed as not attached 1 report error and stop 0 out of tape or paper @@ -1550,7 +1552,7 @@ The terminal output implements these registers: POS 31 number of characters output TIME 24 time from I/O initiation to interrupt -6.2.5 Programmed I/O Devices (LPT) +6.2.5 Line Printer (LPT) The line printer (LPT) writes data to a disk file. The POS register specifies the number of the next data item to be written. Thus, @@ -1594,6 +1596,97 @@ The real-time clock (CLK) implements these registers: TIME2 24 clock frequency, select = 2 TIME3 24 clock frequency, select = 3 +6.2.7 Plotter (PTP) + +The plotter (PLT) 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 plotter. + +The plotter 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.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: @@ -1675,13 +1768,13 @@ The moving head disk controller implements these registers: Error handling is as follows: - error processed as + error processed as - not attached disk not ready + not attached disk not ready - end of file assume rest of disk is zero + end of file assume rest of disk is zero - OS I/O error report error and stop + OS I/O error report error and stop 6.5 Magnetic Tape (MT) @@ -1715,14 +1808,14 @@ The magnetic tape controller implements these registers: Error handling is as follows: - error processed as + error processed as - not attached tape not ready + not attached tape not ready - end of file (read or space) end of physical tape - (write) ignored + end of file (read or space) end of physical tape + (write) ignored - OS I/O error report error and stop + OS I/O error report error and stop 6.6 Symbolic Display and Input @@ -2190,8 +2283,10 @@ The 18b PDP simulators implement several unique stop conditions: - more than XCTMAX nested executes are detected during instruction execution -The 18b PDP loader supports RIM format tapes. The DUMP command is not -implemented. +The PDP-4 and PDP-7 loaders support only RIM format tapes. The PDP-9 +and PDP-15 support both RIM and BIN format tapes. BIN is the default; to +load a RIM format tape, use the -r switch with LOAD. The DUMP command is +not implemented. 8.1 CPU @@ -2235,7 +2330,9 @@ control registers for the interrupt system. 7,9,15 EAE_AC_SIGN 1 EAE AC sign all L 1 link 7,9 EXTM 1 extend mode + 9 EXTM_INIT 1 extend mode value after reset 15 BANKM 1 bank mode + 15 BANKM_INIT 1 bank mode value after reset 7 TRAPM 1 trap mode 9,15 USMD 1 user mode 9,15 USMDBUF 1 user mode buffer @@ -2322,8 +2419,13 @@ Error handling is as follows: 8.2.3 Terminal Input (TTI) The terminal input (TTI) reads from the controling console port. The -input has one option, UC; when set, it automatically converts lower -case input to upper case. +terminal input has 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 terminal input implements these registers: @@ -2533,14 +2635,14 @@ The magnetic tape controller implements these registers: Error handling is as follows: - error processed as + error processed as - not attached tape not ready + not attached tape not ready - end of file (read or space) end of physical tape - (write) ignored + end of file (read or space) end of physical tape + (write) ignored - OS I/O error report error and stop + OS I/O error report error and stop 8.7 Symbolic Display and Input @@ -2910,13 +3012,13 @@ The line printer registers are: Error handling is as follows: - error processed as + error processed as - not attached report error and stop + not attached report error and stop - OS I/O error print error message - if IOCHK set, report error and stop - otherwise, set ERR indicator + OS I/O error print error message + if IOCHK set, report error and stop + otherwise, set ERR indicator 9.4 1407 Inquiry Terminal (INQ) @@ -2947,7 +3049,9 @@ or write locked. SET MTn LOCKED set unit n write locked SET MTn ENABLED set unit n write enabled -Units can also be REMOVEd or ADDed to the configuration. +Units can also be REMOVEd or ADDed to the configuration. The magnetic +tape simulator supports the BOOT command. The bootstrap reads the first +record off tape, starting at location 1, and then branches to it. The magnetic tape controller implements these registers: @@ -2960,16 +3064,16 @@ The magnetic tape controller implements these registers: Error handling is as follows: - error processed as + error processed as - not attached report error and stop + not attached report error and stop - end of file (read or space) end of physical tape - (write) ignored + end of file (read or space) end of physical tape + (write) ignored - OS I/O error print error message - if IOCHK set, report error and stop - otherwise, set ERR indicator + OS I/O error print error message + if IOCHK set, report error and stop + otherwise, set ERR indicator 9.6 Symbolic Display and Input @@ -3094,12 +3198,12 @@ name(s) CPU 2116, 2100, or 21MX CPU with 32KW memory DMA0, DMA1 dual channel DMA controller -PTR,PTP paper tape reader/punch -TTY console terminal -LPT LE8E line printer -CLK 12639C time base generator +PTR,PTP 12597A paper tape reader/punch +TTY 12631C buffered teleprinter +LPT 12653A line printer +CLK 12539A/B/C time base generator DP 12557A cartridge disk controller with four drives -MT 12559 magnetic tape controller with one drives +MT 12559C magnetic tape controller with one drives The HP2100 simulator implements several unique stop conditions: @@ -3193,7 +3297,7 @@ the higher is automatically set to the lower + 1. 10.4 Programmed I/O Devices -10.4.1 Paper Tape Reader (PTR) +10.4.1 12597A-002 Paper Tape Reader (PTR) The paper tape reader (PTR) reads data from a disk file. The POS register specifies the number of the next data item to be read. @@ -3207,6 +3311,7 @@ The paper tape reader implements these registers: name size comments BUF 8 last data item processed + CMD 1 reader enable CTL 1 device/interrupt enable FLG 1 device ready FBF 1 device ready buffer @@ -3227,7 +3332,7 @@ Error handling is as follows: OS I/O error x report error and stop -10.4.2 Paper Tape Punch (PTP) +10.4.2 12597A-005 Paper Tape Punch (PTP) The paper tape punch (PTP) writes data to a disk file. The POS register specifies the number of the next data item to be written. @@ -3238,6 +3343,7 @@ The paper tape punch implements these registers: name size comments BUF 8 last data item processed + CMD 1 punch enable CTL 1 device/interrupt enable FLG 1 device ready FBF 1 device ready buffer @@ -3255,9 +3361,9 @@ Error handling is as follows: OS I/O error x report error and stop -10.4.3 Console Terminal (TTY) +10.4.3 12631C Buffered Teleprinter (TTY) -The console terminal has three units: keyboard (unit 0), printer +The console teleprinter has three units: keyboard (unit 0), printer (unit 1), and punch (unit 2). The keyboard reads from, and the printer writes to, the controlling console port. The punch writes to a disk file. The keyboard has one option, UC; when set, it @@ -3301,6 +3407,7 @@ The line printer implements these registers: name size comments BUF 8 last data item processed + CMD 1 printer enable CTL 1 device/interrupt enable FLG 1 device ready FBF 1 device ready buffer @@ -3319,7 +3426,7 @@ Error handling is as follows: OS I/O error x report error and stop -10.4.5 12639C Time Base Generator (CLK) +10.4.5 12539A/B/C Time Base Generator (CLK) The time base generator (CLK) implements these registers: @@ -3333,9 +3440,9 @@ The time base generator (CLK) implements these registers: TIME0..TIME7 31 clock intervals, select = 0..7 DEVNO 6 current device number (read only) -10.5 12559C Cartridge Disk (DP) +10.5 12557A Cartridge Disk (DP) -The 12559C cartridge disk has two separate devices, a data channel and +The 12557A cartridge disk has two separate devices, a data channel and a device controller. The data channel includes a 128-word (one sector) buffer for reads and writes. The device controller includes the four disk drives. Disk drives can be REMOVEd or ADDed to the configuration. @@ -3347,8 +3454,8 @@ The data channel implements these registers: IBUF 16 input buffer OBUF 16 output buffer BPTR 7 sector buffer pointer - CMD 1 channel enabled - CTL 1 interrupt enabled + CMD 1 channel enable + CTL 1 interrupt enable FLG 1 channel ready FBF 1 channel ready buffer DEVNO 6 current device number (read only) @@ -3363,8 +3470,8 @@ The device controller implements these registers: RARH 2 record address register head RARS 4 record address register sector CNT 5 check record count - CMD 1 controller enabled - CTL 1 interrupt enabled + CMD 1 controller enable + CTL 1 interrupt enable FLG 1 controller ready FBF 1 controller ready buffer EOC 1 end of cylinder pending @@ -3387,7 +3494,7 @@ Error handling is as follows: OS I/O error report error and stop -10.6 12557 Magnetic Tape (MT) +10.6 12559C Magnetic Tape (MT) Magnetic tape options include the ability to make the unit write enabled or write locked. @@ -3395,7 +3502,7 @@ or write locked. SET MT LOCKED set unit write locked SET MT ENABLED set unit write enabled -The 12557 mag tape drive has two separate devices, a data channel and +The 12559C mag tape drive has two separate devices, a data channel and a device controller. The data channel includes a maximum record sized buffer for reads and writes. The device controller includes the tape unit @@ -3430,14 +3537,14 @@ The device controller implements these registers: Error handling is as follows: - error processed as + error processed as - not attached tape not ready + not attached tape not ready - end of file (read or space) end of physical tape - (write) ignored + end of file (read or space) end of physical tape + (write) ignored - OS I/O error report error and stop + OS I/O error report error and stop 10.7 Symbolic Display and Input @@ -3715,249 +3822,7 @@ Line printer output is represented by an ASCII file of lines separated by the newline character. Overprinting is represented by a line ending in return rather than newline. -Appendix 2: Sample Software - -1. PDP-8 - -1.1 ESI-X - -ESI-X is an interactive program for technical computation. It can -execute both immediate commands and stored programs (like BASIC). ESI-X -is provided as both source and as a binary loader format paper-tape -image. For more information see the documentation included with the -program. My thanks to Dave Waks, who wrote the program, and to Paul -Pierce and Tim Litt, who recovered the source from its archival medium. - -To load and run ESI-X: - - sim> load esix.bin - sim> run 5400 - _TYPE 2+2. - 2+2 = 4 - -1.2 FOCAL69 - -FOCAL69 is an interactive program for technical computations. It can -execute both immediate commands and stored programs (like BASIC). FOCAL69 -is provided as a binary loader format paper-tape image. To load and -run FOCAL69: - - sim> load focal69.bin - sim> run 200 - *TYPE 2+2 - = 4.000* - -1.3 PDP-8 OS/8 - -OS/8 is the PDP-8's mass storage-based operating system. It provides a -program development and execution environment for assembler, BASIC, and -FORTRAN programs. OS/8 is provided under license, as is, without fee, by -Digital Equipment Corporation, for non-commercial use only. Please read -the enclosed license agreement for full terms and conditions. This license -agreement must be reproduced with any copy of the OS/8 disk images. My -thanks to Doug Jones of the University of Iowa, who provided the disk -images, and to Digital Equipment Corporation, which provided the license. - -To boot and run OS/8: - - sim> att rx0 os8sys_rx.dsk - sim> att rx1 os8f4_rx.dsk - sim> boot rx0 - - .DA dd-mmm-yy - . - -Note that OS/8 only recognizes upper case characters. The first disk -(drive 0) is the system disk; it also includes BASIC. The second disk -(drive 1) includes FORTRAN. - -2. PDP-11 - -2.1 UNIX V5, V6, V7 - -UNIX was first developed on the PDP-7; its first widespread usage was on -the PDP-11. UNIX provides a program development and execution environment -for assembler and C programs. UNIX V5, V7, V7 for the PDP-11 is provided -under license, as is, without fee, by Santa Cruz Organization (SCO), for -non-commercial use only. Please read the enclosed license agreement for -full terms and conditions. This license must be reproduced with any copy -of the UNIX V5, V6, V7 disk images. My thanks to PUPS, the PDP-11 UNIX -Preservation Society of Australia, which provided the disk images, and to -SCO, which provided the license. - -2.1.1 UNIX V5 - -UNIX V5 is contained on a single RK05 disk image. To boot UNIX: - - sim> set cpu 18b - sim> att rk0 unix_v5_rk.dsk - sim> boot rk - @unix - login: root - #ls -l - -2.1.2 UNIX V6 - -UNIX V6 is contained on three RK05 disk images. To boot UNIX: - - sim> set cpu 18b - sim> att rk0 unix0_v6_rk.dsk - sim> att rk1 unix1_v6_rk.dsk - sim> att rk3 unix3_v6_rk.dsk - sim> boot rk0 - @unix - login: root - # ls -l - -2.1.3 UNIX V7 - -NOTE: The V7 disk images with V2.3c and later releases are new and -replace the prior versions, which were corrupt. - -UNIX V7 is contained on a single RL02 disk image. To boot UNIX: - - sim> set cpu 18b - sim> set rl0 RL02 - sim> att rl0 unix_v7_rl.dsk - sim> boot rl0 - @boot - New Boot, known devices are hp ht rk rl rp tm vt - : rl(0,0)rl2unix - # - -A smaller image is contained on a single RK05 disk image. To boot UNIX: - - sim> set cpu 18b - sim> att rk0 unix_v7_rk.dsk - sim> boot rk0 - @boot - New Boot, known devices are hp ht rk rl rp tm vt - : rk(0,0)rkunix - # STTY -LCASE - # - -2.2 RT-11 - -RT-11 is the PDP-11's single user operating system. It provides a program -development and execution environment for assembler, BASIC, and FORTRAN -programs. RT-11 is provided under license, as is, without fee, by Mentec -Corporation, for non-commercial use ONLY ON THIS SIMULATOR. Please read -the enclosed license agreement for full terms and conditions. This license -agreement must be reproduced with any copy of the RT-11 disk image. My -thanks to John Wilson, a private collector, who provided the disk image -for RT-11 V4; to Megan Gentry, of Digital Equipment Corporation, who -provided the disk image for RT-11 V5.3; and to Mentec Corporation, which -provided the license. - -2.2.1 RT-11 V4 - -RT-11 is contained in a single RK05 disk image. To boot and run RT-11: - - sim> att rk0 rtv4_rk.dsk - sim> boot rk0 - -For RL, RM, and RP series disks, RT-11 expects to find a manufacturer's bad -block table in the last track of the disk. Therefore, INITialization of a -new (all zero's) disk fails, because there is no valid bad block table. To -create a minimal bad block table, use the SET BADBLOCK command. - -2.2.2 RT-11 V5.3 - -RT-11 is contained in a single RL02 disk image. To boot and run RT-11: - - sim> set rl0 rl02 - sim> att rl0 rtv53_rl.dsk - sim> boot rl0 - -This is a full RT-11 distribution kit. It expects the user to copy the -distribution pack and generate a new system. This requires mounting -blank packs on RL1. When a blank pack is attached to the simulator, -a bad block table must be created with the SET BADBLOCK command. - -3. Nova RDOS - -RDOS is the Nova's real-time mass storage operating system. It provides a -program development and execution environment for assembler, BASIC, and -FORTRAN programs. RDOS is provided under license, as is, without fee, by -Data General Corporation, for non-commercial use only. Please read the -enclosed license agreement for full terms and conditions. This license -agreement must be reproduced with any copy of the RDOS disk image. My -thanks to Carl Friend, a private collector, who provided the disk image, -and to Data General Corporation, which provided the license. - -To boot and run RDOS: - - sim> att dp0 rdos_d31.dsk - sim> set tti dasher - sim> boot dp0 - FILENAME? (cr) - DATE (mm/dd/yy)? xx/yy/zz - TIME (hh:mm:ss)? hh:mm:ss - R - list/e - -4. PDP-1 LISP - -PDP-1 LISP is an interactive interpreter for the Lisp language. It can -execute both interactive commands and stored programs. The startup -instructions for LISP are complicated; see the documentation included -with the program for details. My thanks to Peter Deutsch, who wrote the -program, to Gordon Greene, who typed it in from a printed listing, and -to Paul McJones, who helped with the final debug process. - -5. PDP-7 SIM8 - -PDP-7 SIM8 is a PDP-8 simulator for the PDP-7. It implements an 8K -PDP-8/I with keyboard, teleprinter, reader, punch, and line printer. -It provides an interactive console environment for control and debug -of the simulated PDP-8. For more information see the documentation -included with the program. My thanks to Dave Waks, who wrote the -program, and to Paul Pierce and Tim Litt, who recovered the source -from its archival medium. - -To load and run SIM8: - - sim> load sim8.rim - sim> run - AC/ 0000 - -6. 1401 Single Card "Koans" - -One of the art forms for the IBM 1401 was packing useful programs into a -single punched card. Three samples are included: - -i1401_ctolp.cd prints a card deck on the line printer -i1401_ctopu.cd copies a card deck to the card punch -i1401_hello.cd prints "HELLO WORLD" on the line printer and stops - -To use the reproduction cards, simply insert them at the beginning of a -text file, terminated by newline. Attach the modified file to the card -reader, attach a blank file to the output device, and boot the card reader. - -7. HP2116 16K BASIC - -HP BASIC is a paper-tape centric implementation of BASIC for a 16KW -HP2116. Device numbers correspond to the default simulator settings: - - PTR = 10 - TTY = 11 - PTP = 12 - -The program is a complete but early BASIC and has one unsual requirement: -all programs must include a valid END statement to run correctly. My -thanks to Jeff Moffatt for providing the program. - -To load and run BASIC: - - sim> load basic1.abs - sim> run 100 - READY - 10 PRINT SQR(2) - 20 END - RUN - 1.41421 - -Appendix 3: Debug Status +Appendix 2: Debug Status The debug status of each simulated CPU and device is as follows: @@ -3999,7 +3864,34 @@ legend: y = runs operating system or sample program Revision History (since Rev 1.1) -Rev 2.5, Jan, 01 +Rev 2.5a, Dec, 00 + Fixed SCP handling of devices without units + Fixed FLG, FBF initialization in many HP peripherals + Added CMD flop to HP paper tape and line printer + Added status input for HP paper tape punch and TTY + Fixed 1401 bugs found by Dutch Owens + -- 4, 7 char NOPs are legal + -- 1 char B is chained BCE + -- MCE moves whole character, not digit, after first + Added Dutch Owens' 1401 mag tape boot routine + Fixed Nova bugs found by Bruce Ray + -- traps implemented on Nova 3 as well as Nova 4 + -- DIV and DIVS 0/0 set carry + -- RETN sets SP from FP at outset + -- IORST does not clear carry + -- Nova 4 implements two undocumented instructions + Added Bruce Ray's Nova plotter and second terminal modules + Added Charles Owen's Eclipse CPU support + Fixed bugs in 18b PDP's + -- XCT indirect address calculation + -- missing index instructions in PDP-15 + -- bank mode handling in PDP-15 + Added PDP-9/PDP-15 RIM/BIN loader support + Added PDP-9/PDP-15 extend/bank initial state registers + Added PDP-9/PDP-15 half/full duplex support + Moved software documentation to a separate file + +Rev 2.5, Nov, 00 Removed Digital and Compaq from copyrights, as authorized by Compaq Sr VP Bill Strecker Revised save/restore format for 64b simulators @@ -4146,12 +4038,16 @@ Ken Harrenstein PDP-10 simulator Bill Haygood PDP-8 information, simulator, and software Jim Jaeger IBM 1401 information Doug Jones PDP-8 information, simulator, and software +Al Kossow HP 21xx, Varian 620, TI 990, DEC documentation and software Don Lewine Nova documentation and legal permissions Scott McGregor PDP-11 UNIX legal permissions Jeff Moffatt HP 2100 information, documentation, and software Alec Muffett Solaris port testing -Dutch Owen Nova moving head disk debugging, Altair simulator +Dutch Owen Nova moving head disk debugging, Altair simulator, + IBM 1401 diagnostics, debugging, and magtape boot Paul Pierce IBM 1401 diagnostics, media recovery +Bruce Ray Software, documentation, bug fixes, and new devices + for the Nova Craig St Clair PDP documentation Richard Schedler Public repository maintenance Stephen Schultz PDP-11 2.11 BSD debugging diff --git a/simh_swre.txt b/simh_swre.txt new file mode 100644 index 00000000..bf5f1f42 --- /dev/null +++ b/simh_swre.txt @@ -0,0 +1,410 @@ +To: Users +From: Bob Supnik +Subj: Sample Software Packages +Date: 1-Jan-01 + +This memorandum documents the sample software packages available to run +with the SIMH simulators. Many of these packages are available under +limited use licenses; please read the license terms included with the +software. + +The following copyright notice applies to both the SIMH source and binary: + + Original code published in 1993-2000, written by Robert M Supnik + Copyright (c) 1993-2000, 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. + +1. PDP-8 + +1.1 ESI-X + +ESI-X is an interactive program for technical computation. It can +execute both immediate commands and stored programs (like BASIC). ESI-X +is provided as both source and as a binary loader format paper-tape +image. For more information see the documentation included with the +program. My thanks to Dave Waks, who wrote the program, and to Paul +Pierce and Tim Litt, who recovered the source from its archival medium. + +To load and run ESI-X: + + sim> load esix.bin + sim> run 5400 + _TYPE 2+2. + 2+2 = 4 + +1.2 FOCAL69 + +FOCAL69 is an interactive program for technical computations. It can +execute both immediate commands and stored programs (like BASIC). FOCAL69 +is provided as a binary loader format paper-tape image. To load and +run FOCAL69: + + sim> load focal69.bin + sim> run 200 + *TYPE 2+2 + = 4.000* + +1.3 PDP-8 OS/8 + +OS/8 is the PDP-8's mass storage-based operating system. It provides a +program development and execution environment for assembler, BASIC, and +FORTRAN programs. OS/8 is provided under license, as is, without fee, by +Digital Equipment Corporation, for non-commercial use only. Please read +the enclosed license agreement for full terms and conditions. This license +agreement must be reproduced with any copy of the OS/8 disk images. My +thanks to Doug Jones of the University of Iowa, who provided the disk +images, and to Digital Equipment Corporation, which provided the license. + +To boot and run OS/8: + + sim> att rx0 os8sys_rx.dsk + sim> att rx1 os8f4_rx.dsk + sim> boot rx0 + + .DA dd-mmm-yy + . + +Note that OS/8 only recognizes upper case characters. The first disk +(drive 0) is the system disk; it also includes BASIC. The second disk +(drive 1) includes FORTRAN. + +2. PDP-11 + +2.1 UNIX V5, V6, V7 + +UNIX was first developed on the PDP-7; its first widespread usage was on +the PDP-11. UNIX provides a program development and execution environment +for assembler and C programs. UNIX V5, V7, V7 for the PDP-11 is provided +under license, as is, without fee, by Santa Cruz Organization (SCO), for +non-commercial use only. Please read the enclosed license agreement for +full terms and conditions. This license must be reproduced with any copy +of the UNIX V5, V6, V7 disk images. My thanks to PUPS, the PDP-11 UNIX +Preservation Society of Australia, which provided the disk images, and to +SCO, which provided the license. + +2.1.1 UNIX V5 + +UNIX V5 is contained on a single RK05 disk image. To boot UNIX: + + sim> set cpu 18b + sim> att rk0 unix_v5_rk.dsk + sim> boot rk + @unix + login: root + #ls -l + +2.1.2 UNIX V6 + +UNIX V6 is contained on three RK05 disk images. To boot UNIX: + + sim> set cpu 18b + sim> att rk0 unix0_v6_rk.dsk + sim> att rk1 unix1_v6_rk.dsk + sim> att rk3 unix3_v6_rk.dsk + sim> boot rk0 + @unix + login: root + # ls -l + +2.1.3 UNIX V7 + +NOTE: The V7 disk images with V2.3c and later releases are new and +replace the prior versions, which were corrupt. + +UNIX V7 is contained on a single RL02 disk image. To boot UNIX: + + sim> set cpu 18b + sim> set rl0 RL02 + sim> att rl0 unix_v7_rl.dsk + sim> boot rl0 + @boot + New Boot, known devices are hp ht rk rl rp tm vt + : rl(0,0)rl2unix + # + +A smaller image is contained on a single RK05 disk image. To boot UNIX: + + sim> set cpu 18b + sim> att rk0 unix_v7_rk.dsk + sim> boot rk0 + @boot + New Boot, known devices are hp ht rk rl rp tm vt + : rk(0,0)rkunix + # STTY -LCASE + # + +2.2 RT-11 + +RT-11 is the PDP-11's single user operating system. It provides a program +development and execution environment for assembler, BASIC, and FORTRAN +programs. RT-11 is provided under license, as is, without fee, by Mentec +Corporation, for non-commercial use ONLY ON THIS SIMULATOR. Please read +the enclosed license agreement for full terms and conditions. This license +agreement must be reproduced with any copy of the RT-11 disk image. My +thanks to John Wilson, a private collector, who provided the disk image +for RT-11 V4; to Megan Gentry, of Digital Equipment Corporation, who +provided the disk image for RT-11 V5.3; and to Mentec Corporation, which +provided the license. + +2.2.1 RT-11 V4 + +RT-11 is contained in a single RK05 disk image. To boot and run RT-11: + + sim> att rk0 rtv4_rk.dsk + sim> boot rk0 + +For RL, RM, and RP series disks, RT-11 expects to find a manufacturer's bad +block table in the last track of the disk. Therefore, INITialization of a +new (all zero's) disk fails, because there is no valid bad block table. To +create a minimal bad block table, use the SET BADBLOCK command. + +2.2.2 RT-11 V5.3 + +RT-11 is contained in a single RL02 disk image. To boot and run RT-11: + + sim> set rl0 rl02 + sim> att rl0 rtv53_rl.dsk + sim> boot rl0 + +This is a full RT-11 distribution kit. It expects the user to copy the +distribution pack and generate a new system. This requires mounting +blank packs on RL1. When a blank pack is attached to the simulator, +a bad block table must be created with the SET BADBLOCK command. + +3. Nova RDOS + +RDOS is the Nova's real-time mass storage operating system. It provides a +program development and execution environment for assembler, BASIC, and +FORTRAN programs. RDOS is provided under license, as is, without fee, by +Data General Corporation, for non-commercial use only. Please read the +enclosed license agreement for full terms and conditions. This license +agreement must be reproduced with any copy of the RDOS disk image. My +thanks to Carl Friend, a private collector, who provided the disk image, +and to Data General Corporation, which provided the license. + +To boot and run RDOS: + + sim> att dp0 rdos_d31.dsk + sim> set tti dasher + sim> boot dp0 + FILENAME? (cr) + DATE (mm/dd/yy)? xx/yy/zz + TIME (hh:mm:ss)? hh:mm:ss + R + list/e + +4. PDP-1 LISP + +PDP-1 LISP is an interactive interpreter for the Lisp language. It can +execute both interactive commands and stored programs. The startup +instructions for LISP are complicated; see the documentation included +with the program for details. My thanks to Peter Deutsch, who wrote the +program, to Gordon Greene, who typed it in from a printed listing, and +to Paul McJones, who helped with the final debug process. + +5. PDP-7 SIM8 + +PDP-7 SIM8 is a PDP-8 simulator for the PDP-7. It implements an 8K +PDP-8/I with keyboard, teleprinter, reader, punch, and line printer. +It provides an interactive console environment for control and debug +of the simulated PDP-8. For more information see the documentation +included with the program. My thanks to Dave Waks, who wrote the +program, and to Paul Pierce and Tim Litt, who recovered the source +from its archival medium. + +To load and run SIM8: + + sim> load sim8.rim + sim> run + AC/ 0000 + +6. PDP-15 FOCAL + +FOCAL15 is an interactive program for technical computations. It can +execute both immediate commands and stored programs (like BASIC). FOCAL15 +is provided as a binary loader format paper-tape image. My thanks to Al +Kossow, who provided the binary image. To load and run FOCAL15: + + sim> load focal15.bin + sim> run + *TYPE FSQT(2),! + = 1.4142 + * + +7. IBM 1401 + +7.1 Single Card "Koans" + +One of the art forms for the IBM 1401 was packing useful programs into a +single punched card. Three samples are included: + +i1401_ctolp.cd prints a card deck on the line printer +i1401_ctopu.cd copies a card deck to the card punch +i1401_hello.cd prints "HELLO WORLD" on the line printer and stops + +To use the reproduction cards, simply insert them at the beginning of a +text file, terminated by newline. Attach the modified file to the card +reader, attach a blank file to the output device, and boot the card reader. + +7.2 Diagnostic Tape + +The software and writeup were provided by Charles Owens. + +This 1401 Diagnostics tape is a bootable tape containing a series of 1401 +diagnostics dating from about 1962. The 1407 Inquiry console is not used; +all control is via the front panel. + +To run in the simulator, attach thusly: + + sim> attach mt1 1401diag.mt + sim> attach lpt errorlist.txt + sim> boot mt1 + +The simulator will halt with IS = 433. At this point, you can set options +through the sense switches and memory. + +D 1252 "1" Will cause headings to print for each test run. + Otherwise no printing will occur unless there are errors. + +D SSB 1 Loop if an error is detected. + +D SSC 1 Prints all test cases not just errors. + +D SSD 1 Repeat the test run over and over. + +D SSE 1 Halt if any error is detected, otherwise continue. + +When you continue from this halt (use C to CON), the simulator will halt +at 3001. Enter C again and the tape will spin thru a series of basic +CPU diagnostics. + +7.3 SPS + +The software and writeup were provided by Charles Owens. + +sps1.obj and sps2.obj are the object card decks are the "Symbolic +Programming System", a primitive assembler for the 1401 that predates +the better known and more functional Autocoder. + +To use SPS, write an SPS program using your favourite editor (two +examples are provided, hello.sps and diaglist.sps). SPS decks are +not free-format, but operands must be placed in columns: + + 1 - 5 Line Count (optional) + 6 - 7 Count (number of characters when defining a constant). + 8 - 13 Label (six characters must start with alphabetic). +14 - 16 Opcode: Examples: + A = Add + B = Branch (must be d-mod for conditional) + BWZ = Branch if Wordmark or Zone + C = Compare + CC = Carriage Control (printer) + CS = CLear Storage + CU = Control Unit (e.g. tape) + CW = Clear Workmark + D = Divide + DC = Define Constant (no wordmark) + DCW = Define Constant (starts in 24, length in 6-7) + END = End of program + LCA = Load Characters + H = Halt + M = Multiply + MCE = Move and Edit + MCS = Move and Supress Zeros + MCW = Move Characters + MN = Move Numeric + MZ = Move Zone + ORG = Define Origin Point + P = Punch Card + R = Read Card + S = Subtract + SS = Stacker Select + SW = Set Wordmark + W = Write Line + ZA = Zero and Add + ZS = Zero and Subtract + Tape: + MCW %UX YYY W Write Tape from addr YYY w/o wordmarks) + LCA %UX YYY W Write Tape, Unit X from addr YYY w/wordmarks) + MCW %UX YYY R Read Tape from addr YYY w/o wordmarks) + LCA %UX YYY R Read Tape, Unit X from addr YYY w/wordmarks) + CU %UX M Write Tape Mark + CU %UX E Skip and Blank Tape + CU %UX B Backspace Record + CU %UX R Rewind Tape + CU %UX U Rewind and Unlaod tape +17 - 22 Address for A-operand (label or 4-digit actual address) +23 - 23 blank, + or - to adjust A-operand by a constant +24 - 26 3-digit number to adjust A-operand by if 23 is + or - +27 - 27 Index (?) +28 - 33 Address for B-operand +34 - 34 Blank, + or - +35 - 37 3-digit number of adjust B-address by if 34 is + or - +38 - 38 Index (?) +39 - 39 D-modifier for this instruction. Notes: + / = Compare is unequal + S = Branch if Compare Equal + T = B is less than A + U = B is greater than A + L = Tape read error + K = Tape end of reel +40 - 55 Comments + +The SPS deck should start with an ORG operation to specify where in storage +the program starts, and end with an END card, with an optional A-operand +showing where to start execution. + +To assemble an SPS program, place the SPS source between the SPS1.OBJ and +the SPS2.OBJ deck, and another copy of the same source after the SPS2.OBJ +deck (SPS is a two-pass assembler). SPS prints a listing on LPT and punches +an object deck on CDP, ready to run. + +A UNIX command script to assemble an SPS deck painlessly is in "sps". To +use the script, enter "sps programname". The script creates programname.lst +for the listing and programname.obj for the object deck. Windows users +are out of luck, for now. + +8. HP2116 16K BASIC + +HP BASIC is a paper-tape centric implementation of BASIC for a 16KW +HP2116. Device numbers correspond to the default simulator settings: + + PTR = 10 + TTY = 11 + PTP = 12 + +The program is a complete but early BASIC and has one unsual requirement: +all programs must include a valid END statement to run correctly. My +thanks to Jeff Moffatt for providing the program. + +To load and run BASIC: + + sim> load basic1.abs + sim> run 100 + READY + 10 PRINT SQR(2) + 20 END + RUN + 1.41421 + +[end simh_swre.txt]