1
0
mirror of https://github.com/simh/simh.git synced 2026-05-01 22:06:00 +00:00

Notes For V3.0-2

RESTRICTION: The FP15 and XVM features of the PDP-15 are only partially
debugged.  Do NOT enable these features for normal operations.

1. New Features in 3.0-2

1.1 PDP-1

- The LOAD command takes an optional argument specifying the memory field
  to be loaded.
- The PTR BOOT command takes its starting memory field from the TA (address
  switch) register.

2. Bugs Fixed in 3.0-2

2.1 SCP and libraries

- Fixed end of file problem in dep, idep.
- Fixed handling of trailing spaces in dep, idep.

2.2 PDP-1

- Fixed system hang if continue after PTR error.
- Fixed PTR to start/stop on successive rpa instructions.

2.3 PDP 18b family

- Fixed priorities in PDP-15 API (differs from PDP-9).
- Fixed sign handling in PDP-15 EAE unsigned mul/div (differs from PDP-9).
- Fixed bug in CAF, clears API subsystem.

2.4 1401

- Fixed tape read end-of-record handling based on real 1401.
- Added diagnostic read (space forward).

2.5 1620

- Fixed bug in immediate index add (found by Michael Short).

3. New Features in 3.0 vs prior releases

3.1 SCP and Libraries

- Added ASSIGN/DEASSIGN (logical name) commands.
- Changed RESTORE to unconditionally detach files.
- Added E11 and TPC format support to magtape library.
- Fixed bug in SHOW CONNECTIONS.
- Added USE_ADDR64 support

3.2 All magtapes

- Magtapes support SIMH format, E11 format, and TPC format (read only).
- SET <tape_unit> FORMAT=format sets the specified tape unit's format.
- SHOW <tape_unit> FORMAT displays the specified tape unit's format.
- Tape format can also be set as part of the ATTACH command, using
  the -F switch.

3.3 VAX

- VAX can be compiled without USE_INT64.
- If compiled with USE_INT64 and USE_ADDR64, RQ and TQ controllers support
  files > 2GB.
- VAX ROM has speed control (SET ROM DELAY/NODELAY).

3.4 PDP-1

- Added block loader format support to LOAD.
- Changed BOOT PTR to allow loading of all of the first bank of memory.

3.5 PDP-18b Family

- Added PDP-4 EAE support.
- Added PDP-15 FP15 support.
- Added PDP-15 XVM support.
- Added PDP-15 "re-entrancy ECO".
- Added PDP-7, PDP-9, PDP-15 hardware RIM loader support in BOOT PTR.

4. Bugs Fixed in 3.0 vs prior releases

4.1 VAX

- Fixed CVTfi bug: integer overflow not set if exponent out of range
- Fixed EMODx bugs:
  o First and second operands reversed
  o Separated fraction received wrong exponent
  o Overflow calculation on separated integer incorrect
  o Fraction not set to zero if exponent out of range
- Fixed interval timer and ROM access to pass power-up self-test even on very
  fast host processors (fixes from Mark Pizzolato).
- Fixed bug in user disk size (found by Chaskiel M Grundman).

4.2 1401

- Fixed mnemonic, instruction lengths, and reverse scan length check bug for MCS.
- Fixed MCE bug, BS off by 1 if zero suppress.
- Fixed chaining bug, D lost if return to SCP.
- Fixed H branch, branch occurs after continue.
- Added check for invalid 8 character MCW, LCA.
- Fixed magtape load-mode end of record response.
- Revised fetch to model hardware more closely.

4.3 Nova

- Fixed DSK variable size interaction with restore.
- Fixed bug in DSK set size routine.

4.4 PDP-1

- Fixed DT variable size interaction with restore.
- Updated CPU, line printer, standard devices to detect indefinite I/O wait.
- Fixed incorrect logical, missing activate, break in drum simulator.
- Fixed bugs in instruction decoding, overprinting for line printer.

4.5 PDP-11

- Fixed DT variable size interaction with restore.
- Fixed bug in MMR1 update (found by Tim Stark).
- Added XQ features and fixed bugs:
  o Corrected XQ interrupts on IE state transition (code by Tom Evans).
  o Added XQ interrupt clear on soft reset.
  o Removed XQ interrupt when setting XL or RL (multiple people).
  o Added SET/SHOW XQ STATS.
  o Added SHOW XQ FILTERS.
  o Added ability to split received packet into multiple buffers.
  o Added explicit runt and giant packet processing.
- Fixed bug in user disk size (found by Chaskiel M Grundman).

4.6 PDP-18B

- Fixed DT, RF variable size interaction with restore.
- Fixed MT bug in MTTR.
- Fixed bug in PDP-4 line printer overprinting.
- Fixed bug in PDP-15 memory protect/skip interaction.
- Fixed bug in RF set size routine.
- Increased PTP TIME for PDP-15 operating systems.

4.7 PDP-8

- Fixed DT, DF, RF, RX variable size interaction with restore.
- Fixed MT bug in SKTR.
- Fixed bug in DF, RF set size routine.

4.8 HP2100

- Fixed bug in DP (13210A controller only), DQ read status.
- Fixed bug in DP, DQ seek complete.
- Fixed DR drum sizes.
- Fixed DR variable capacity interaction with SAVE/RESTORE.

4.9 GRI

- Fixed bug in SC queue pointer management.

4.10 PDP-10

- Fixed bug in RP read header.

4.11 Ibm1130

- Fixed bugs found by APL 1130.

4.12 Altairz80

- Fixed bug in real-time clock on Windows host.
This commit is contained in:
Bob Supnik
2003-09-15 18:00:00 -07:00
committed by Mark Pizzolato
parent f9564b81b9
commit b2101ecdd4
21 changed files with 554 additions and 216 deletions

View File

@@ -25,6 +25,9 @@
cpu PDP-4/7/9/15 central processor
31-Aug-03 RMS Added instruction history
Fixed PDP-15-specific implementation of API priorities
16-Aug-03 RMS Fixed PDP-15-specific handling of EAE unsigned mul/div
27-Jul-03 RMS Added FP15 support
Added XVM support
Added EAE option to PDP-4
@@ -274,6 +277,18 @@
#define UNIT_XVM (1 << UNIT_V_XVM)
#define UNIT_MSIZE (1 << UNIT_V_MSIZE)
#define HIST_SIZE 4096
#define HIST_API 0x40000000
#define HIST_PI 0x20000000
#define HIST_M_LVL 0x3F
#define HIST_V_LVL 6
struct InstHistory {
int32 pc;
int32 ir;
int32 ir1;
int32 lac;
int32 mq; };
#define XVM (cpu_unit.flags & UNIT_XVM)
#define RELOC (cpu_unit.flags & UNIT_RELOC)
#define PROT (cpu_unit.flags & UNIT_PROT)
@@ -338,6 +353,9 @@ int16 pcq[PCQ_SIZE] = { 0 }; /* PC queue */
#endif
int32 pcq_p = 0; /* PC queue ptr */
REG *pcq_r = NULL; /* PC queue reg ptr */
int32 hst_p = 0; /* history pointer */
int32 hst_lnt = 0; /* history length */
static struct InstHistory hst[HIST_SIZE] = { { 0 } }; /* instruction history */
extern int32 sim_int_char;
extern int32 sim_interval;
@@ -350,6 +368,10 @@ 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);
t_stat cpu_reset (DEVICE *dptr);
t_stat cpu_set_size (UNIT *uptr, int32 val, char *cptr, void *desc);
t_stat cpu_set_hist (UNIT *uptr, int32 val, char *cptr, void *desc);
t_stat cpu_show_hist (FILE *st, UNIT *uptr, int32 val, void *desc);
void cpu_inst_hist (int32 addr, int32 inst);
void cpu_intr_hist (int32 flag, int32 lvl);
int32 upd_iors (void);
int32 api_eval (int32 *pend);
t_stat Read (int32 ma, int32 *dat, int32 cyc);
@@ -511,6 +533,8 @@ MTAB cpu_mod[] = {
{ UNIT_MSIZE, 114688, NULL, "112K", &cpu_set_size },
{ UNIT_MSIZE, 131072, NULL, "128K", &cpu_set_size },
#endif
{ MTAB_XTD|MTAB_VDV|MTAB_NMO, 0, "HISTORY", "HISTORY",
&cpu_set_hist, &cpu_show_hist },
{ 0 } };
DEVICE cpu_dev = {
@@ -564,7 +588,7 @@ if (trap_pending) { /* trap pending? */
Write (0, MB, WR); /* save in 0 */
PC = 2; } /* fetch next from 2 */
#endif
if (ion && !ion_defer && int_pend) { /* interrupt? */
if (int_pend && ion && !ion_defer) { /* interrupt? */
PCQ_ENTRY; /* save old PC */
MB = Jms_word (usmd); /* save state */
ion = 0; /* interrupts off */
@@ -599,6 +623,7 @@ if (trap_pending) { /* trap pending? */
if (api_int && !ion_defer) { /* API intr? */
int32 i, lvl = api_int - 1; /* get req level */
if (hst_lnt) cpu_intr_hist (HIST_API, lvl); /* record */
api_act = api_act | (API_ML0 >> lvl); /* set level active */
if (lvl >= API_HLVL) { /* software req? */
MA = ACH_SWRE + lvl - API_HLVL; /* vec = 40:43 */
@@ -619,13 +644,16 @@ if (api_int && !ion_defer) { /* API intr? */
xct_count = 0;
goto xct_instr; }
if (!(api_enb && api_act) && ion && !ion_defer && int_pend) {
if (int_pend && ion && !ion_defer && /* int pending, enabled? */
!(api_enb && (api_act & API_MASKPI))) { /* API off or not masking PI? */
PCQ_ENTRY; /* save old PC */
if (hst_lnt) cpu_intr_hist (HIST_PI, 0); /* record */
MB = Jms_word (usmd); /* save state */
ion = 0; /* interrupts off */
#if defined (PDP9) /* PDP-9, */
memm = 0; /* extend off */
#else /* PDP-15 */
ion_defer = 2; /* free instruction */
if (!(cpu_unit.flags & UNIT_NOAPI)) { /* API? */
api_act = api_act | API_ML3; /* set lev 3 active */
api_int = api_eval (&int_pend); } /* re-evaluate */
@@ -651,6 +679,7 @@ PC = Incr_addr (PC); /* increment PC */
xct_instr: /* label for XCT */
if (Read (MA, &IR, FE)) continue; /* fetch instruction */
if (hst_lnt) cpu_inst_hist (MA, IR); /* history? */
if (ion_defer) ion_defer = ion_defer - 1; /* count down defer */
if (sim_interval) sim_interval = sim_interval - 1;
@@ -971,7 +1000,7 @@ case 036: /* OPR, dir */
case 7: /* RTL RTR */
#if defined (PDP15) /* PDP-15 */
LAC = ((LAC >> 9) & 0777) | ((LAC & 0777) << 9) |
(LAC & LINK); /* BSW */
(LAC & LINK); /* BSW */
#else /* PDP-4,-7,-9 */
reason = stop_inst; /* undefined */
#endif
@@ -1014,6 +1043,12 @@ case 033: case 032: /* EAE */
if (IR & 02) LAC = LAC | MQ; /* IR<16>? or MQ */
if (IR & 01) LAC = LAC | ((-SC) & 077); /* IR<17>? or SC */
break;
/* EAE, continued
Multiply uses a shift and add algorithm. The PDP-15, unlike prior
implementations, factors IR<6> (signed multiply) into the calculation
of the result sign. */
case 1: /* multiply */
if (Read (PC, &MB, FE)) break; /* get next word */
@@ -1027,20 +1062,19 @@ case 033: case 032: /* EAE */
LAC = LAC >> 1; /* shift AC'MQ right */
SC = (SC - 1) & 077; } /* decrement SC */
while (SC != 0); /* until SC = 0 */
#if defined (PDP15)
if ((IR & 0004000) && (eae_ac_sign ^ link_init)) {
#else
if (eae_ac_sign ^ link_init) { /* result negative? */
#endif
LAC = LAC ^ DMASK;
MQ = MQ ^ DMASK; }
break;
/* EAE, continued
Divide uses a non-restoring divide. This code duplicates the PDP-7
algorithm, except for its use of two's complement arithmetic instead
of 1's complement.
The quotient is generated in one's complement form; therefore, the
quotient is complemented if the input operands had the same sign
(that is, if the quotient is positive). */
/* Divide uses a non-restoring divide. Divide uses a subtract and shift
algorithm. The quotient is generated in true form. The PDP-15, unlike
prior implementations, factors IR<6> (signed multiply) into the calculation
of the result sign.*/
case 3: /* divide */
if (Read (PC, &MB, FE)) break; /* get next word */
@@ -1058,12 +1092,17 @@ case 033: case 032: /* EAE */
t = (LAC >> 18) & 1; /* quotient bit */
if (SC > 1) LAC = /* skip if last */
((LAC << 1) | (MQ >> 17)) & LACMASK;
MQ = ((MQ << 1) | t) & DMASK; /* shift in quo bit */
MQ = ((MQ << 1) | (t ^ 1)) & DMASK; /* shift in quo bit */
SC = (SC - 1) & 077; } /* decrement SC */
while (SC != 0); /* until SC = 0 */
if (t) LAC = (LAC + MB) & LACMASK;
if (eae_ac_sign) LAC = LAC ^ DMASK; /* sgn rem = sgn divd */
if ((eae_ac_sign ^ link_init) == 0) MQ = MQ ^ DMASK;
if (eae_ac_sign) LAC = LAC ^ DMASK; /* sgn rem = sgn divd */
#if defined (PDP15)
if ((IR & 0004000) && (eae_ac_sign ^ link_init))
#else
if (eae_ac_sign ^ link_init) /* result negative? */
#endif
MQ = MQ ^ DMASK;
break;
/* EAE, continued
@@ -1212,7 +1251,7 @@ case 035: /* index operates */
case 034: /* IOT */
#if defined (PDP15)
if (IR & 0010000) { /* floating point? */
fp15 (IR); /* process */
reason = fp15 (IR); /* process */
break; }
#endif
if ((api_usmd | usmd) && /* user, not XVM UIOT? */
@@ -1286,7 +1325,9 @@ case 034: /* IOT */
break;
case 033: /* CPU control */
if ((pulse == 001) || (pulse == 041)) PC = Incr_addr (PC);
else if (pulse == 002) reset_all (1); /* CAF - skip CPU */
else if (pulse == 002) { /* CAF */
reset_all (1); /* reset all exc CPU */
api_enb = api_req = api_act = 0; } /* reset API system */
else if (pulse == 044) rest_pending = 1; /* DBR */
if (((cpu_unit.flags & UNIT_NOAPI) == 0) && (pulse & 004)) {
int32 t = api_ffo[api_act & 0377];
@@ -1348,7 +1389,9 @@ case 034: /* IOT */
break;
case 033: /* CPU control */
if ((pulse == 001) || (pulse == 041)) PC = Incr_addr (PC);
else if (pulse == 002) reset_all (2); /* CAF - skip CPU, FP15 */
else if (pulse == 002) { /* CAF */
reset_all (2); /* reset all exc CPU, FP15 */
api_enb = api_req = api_act = 0; } /* reset API system */
else if (pulse == 044) rest_pending = 1; /* DBR */
if (((cpu_unit.flags & UNIT_NOAPI) == 0) && (pulse & 004)) {
int32 t = api_ffo[api_act & 0377];
@@ -1881,3 +1924,83 @@ for (i = p = 0; (dptr = sim_devices[i]) != NULL; i++) { /* add devices */
} /* end for i */
return FALSE;
}
/* Set history */
t_stat cpu_set_hist (UNIT *uptr, int32 val, char *cptr, void *desc)
{
int32 i, lnt;
t_stat r;
if (cptr == NULL) {
for (i = 0; i < HIST_SIZE; i++) hst[i].pc = 0;
return SCPE_OK; }
lnt = (int32) get_uint (cptr, 10, HIST_SIZE, &r);
if (r != SCPE_OK) return SCPE_ARG;
hst_lnt = lnt;
return SCPE_OK;
}
/* Show history */
t_stat cpu_show_hist (FILE *st, UNIT *uptr, int32 val, void *desc)
{
int32 l, j, k, di;
t_value sim_eval[2];
struct InstHistory *h;
extern t_stat fprint_sym (FILE *ofile, t_addr addr, t_value *val,
UNIT *uptr, int32 sw);
if (hst_lnt == 0) return SCPE_NOFNC; /* enabled? */
di = hst_p + HIST_SIZE - hst_lnt; /* work forward */
for (k = 0; k < hst_lnt; k++) { /* print specified */
h = &hst[(di++) % HIST_SIZE]; /* entry pointer */
if (h->pc == 0) continue; /* filled in? */
if (h->pc & (HIST_API | HIST_PI)) { /* interrupt event? */
if (h->pc & HIST_PI) /* PI? */
fprintf (st, "%06o PI LVL 0-4 =", h->pc & AMASK);
else fprintf (st, "%06o API %d LVL 0-4 =", h->pc & AMASK, h->mq);
for (j = API_HLVL; j >= 0; j--)
fprintf (st, " %02o", (h->ir >> (j * HIST_V_LVL)) & HIST_M_LVL);
}
else { /* instruction */
l = (h->lac >> 18) & 1; /* link */
fprintf (st, "%06o %o %06o %06o ", h->pc, l, h->lac & DMASK, h->mq);
sim_eval[0] = h->ir;
sim_eval[1] = h->ir1;
if ((fprint_sym (st, h->pc, sim_eval, &cpu_unit, SWMASK ('M'))) > 0)
fprintf (st, "(undefined) %06o", h->ir);
} /* end else instruction */
fputc ('\n', st); /* end line */
} /* end for */
return SCPE_OK;
}
/* Record events in history table */
void cpu_inst_hist (int32 addr, int32 inst)
{
hst[hst_p].pc = addr;
hst[hst_p].ir = inst;
if (cpu_ex (&hst[hst_p].ir1, (addr + 1) & AMASK, &cpu_unit, SWMASK ('V')))
hst[hst_p].ir1 = 0;
hst[hst_p].lac = LAC;
hst[hst_p].mq = MQ;
hst_p = (hst_p + 1) % HIST_SIZE;
return;
}
void cpu_intr_hist (int32 flag, int32 lvl)
{
int32 j;
hst[hst_p].pc = PC | flag;
hst[hst_p].ir = 0;
for (j = 0; j < API_HLVL+1; j++) hst[hst_p].ir =
(hst[hst_p].ir << HIST_V_LVL) | (int_hwre[j] & HIST_M_LVL);
hst[hst_p].ir1 = 0;
hst[hst_p].lac = 0;
hst[hst_p].mq = lvl;
hst_p = (hst_p + 1) % HIST_SIZE;
return;
}