1
0
mirror of https://github.com/simh/simh.git synced 2026-03-27 02:15:16 +00:00

Notes For V3.7-0

1. New Features

1.1 3.7-0

1.1.1 SCP

- Added SET THROTTLE and SET NOTHROTTLE commands to regulate simulator
  execution rate and host resource utilization.
- Added idle support (based on work by Mark Pizzolato).
- Added -e to control error processing in nested DO commands (from
  Dave Bryan).

1.1.2 HP2100

- Added Double Integer instructions, 1000-F CPU, and Floating Point
  Processor (from Dave Bryan).
- Added 2114 and 2115 CPUs, 12607B and 12578A DMA controllers, and
  21xx binary loader protection (from Dave Bryan).

1.1.3 Interdata

- Added SET IDLE and SET NOIDLE commands to idle the simulator in wait
  state.

1.1.4 PDP-11

- Added SET IDLE and SET NOIDLE commands to idle the simulator in wait
  state (WAIT instruction executed).
- Added TA11/TU60 cassette support.

1.1.5 PDP-8

- Added SET IDLE and SET NOIDLE commands to idle the simulator in wait
  state (keyboard poll loop or jump-to-self).
- Added TA8E/TU60 cassette support.

1.1.6 PDP-1

- Added support for 16-channel sequence break system.
- Added support for PDP-1D extended features and timesharing clock.
- Added support for Type 630 data communications subsystem.

1.1.6 PDP-4/7/9/15

- Added SET IDLE and SET NOIDLE commands to idle the simulator in wait
  state (keyboard poll loop or jump-to-self).

1.1.7 VAX, VAX780

- Added SET IDLE and SET NOIDLE commands to idle the simulator in wait
  state (more than 200 cycles at IPL's 0, 1, or 3 in kernel mode).

1.1.8 PDP-10

- Added SET IDLE and SET NOIDLE commands to idle the simulator in wait
  state (operating system dependent).
- Added CD20 (CD11) support.

2. Bugs Fixed

Please see the revision history on http://simh.trailing-edge.com or
in the source module sim_rev.h.
This commit is contained in:
Bob Supnik
2007-02-03 14:59:00 -08:00
committed by Mark Pizzolato
parent 15919a2dd7
commit 53d02f7fa7
161 changed files with 18604 additions and 6903 deletions

View File

@@ -700,7 +700,7 @@ switch (op) { /* case on opcode */
fpd = 1; /* set FPD */
R[4] = R[4] & 0377; /* mask fill */
c = t = 0;
for (i = 0; (R[0] || R[2]); ) { /* until cnts == 0 */
for (i = 0; (R[0] || R[2]); ) { /* until cnts == 0 */
if (R[0]) c = ReadB (R[1] | dsenable); /* get src1 or fill */
else c = R[4];
if (R[2]) t = ReadB (R[3] | dsenable); /* get src2 or fill */
@@ -1192,15 +1192,18 @@ return TestDstr (src); /* clean -0 */
dsrc = decimal string descriptor
src = decimal string structure
flag = numeric/packed flag
PSW.NZ are also set to their proper values
PSW.V will be set on overflow; it must be initialized elsewhere
(to allow for external overflow calculations)
(to allow for external overflow calculations)
The rules for the stored sign and the PSW sign are:
- Stored sign is negative if input is negative, string type
is signed, and the result is non-zero or there was overflow
- PSW sign is negative if input is negative, string type is
signed, and the result is non-zero
- Stored sign is negative if input is negative, string type
is signed, and the result is non-zero or there was overflow
- PSW sign is negative if input is negative, string type is
signed, and the result is non-zero
Thus, the stored sign and the PSW sign will differ in one case:
a negative zero generated by overflow is stored with a negative
sign, but PSW.N is clear
@@ -1265,16 +1268,18 @@ return;
cy = carry in
Output = 1 if carry, 0 if no carry
This algorithm courtesy Anton Chernoff, circa 1992 or even earlier
This algorithm courtesy Anton Chernoff, circa 1992 or even earlier.
We trace the history of a pair of adjacent digits to see how the
carry is fixed; each parenthesized item is a 4b digit.
Assume we are adding:
(a)(b) I
+ (x)(y) J
First compute I^J:
(a^x)(b^y) TMP
Note that the low bit of each digit is the same as the low bit of
@@ -1283,6 +1288,7 @@ return;
Now compute I+J+66 to get decimal addition with carry forced left
one digit:
(a+x+6+carry mod 16)(b+y+6 mod 16) SUM
Note that if there was a carry from b+y+6, then the low bit of the
@@ -1357,6 +1363,7 @@ return 0;
Arguments:
dsrc = decimal string structure
Returns the non-zero length of the string, in int32 units
If the string is zero, the sign is cleared
*/
@@ -1395,8 +1402,8 @@ return ((nz - 1) * 8) + i;
mtable[10] = array of decimal string structures
Note that dsrc has a high order zero nibble; this
guarantees that the largest multiple won't overflow
Also note that mtable[0] is not filled in
guarantees that the largest multiple won't overflow.
Also note that mtable[0] is not filled in.
*/
void CreateTable (DSTR *dsrc, DSTR mtable[10])
@@ -1560,7 +1567,7 @@ fpd = 0; /* instr done */
return;
}
/* Test for CIS mid-instruction interrupt - stub for now */
/* Test for CIS mid-instruction interrupt */
t_bool cis_int_test (int32 cycles, int32 oldpc, t_stat *st)
{

View File

@@ -25,6 +25,8 @@
cpu PDP-11 CPU
27-Oct-06 RMS Added idle support
18-Oct-06 RMS Fixed bug in ASH -32 C value
24-May-06 RMS Added instruction history
03-May-06 RMS Fixed XOR operand fetch order for 11/70-style systems
22-Sep-05 RMS Fixed declarations (from Sterling Garwood)
@@ -220,8 +222,8 @@
#define calc_is(md) ((md) << VA_V_MODE)
#define calc_ds(md) (calc_is((md)) | ((MMR3 & dsmask[(md)])? VA_DS: 0))
#define calc_MMR1(val) ((MMR1)? (((val) << 8) | MMR1): (val))
#define GET_SIGN_W(v) ((v) >> 15)
#define GET_SIGN_B(v) ((v) >> 7)
#define GET_SIGN_W(v) (((v) >> 15) & 1)
#define GET_SIGN_B(v) (((v) >> 7) & 1)
#define GET_Z(v) ((v) == 0)
#define JMP_PC(x) PCQ_ENTRY; PC = (x)
#define BRANCH_F(x) PCQ_ENTRY; PC = (PC + (((x) + (x)) & 0377)) & 0177777
@@ -300,6 +302,7 @@ extern UNIT clk_unit, pclk_unit;
extern int32 sim_int_char;
extern uint32 sim_switches;
extern uint32 sim_brk_types, sim_brk_dflt, sim_brk_summ; /* breakpoint info */
extern t_bool sim_idle_enab;
extern DEVICE *sim_devices[];
extern CPUTAB cpu_tab[];
@@ -376,7 +379,7 @@ int32 trap_clear[TRAP_V_MAX] = { /* trap clears */
cpu_mod CPU modifier list
*/
UNIT cpu_unit = { UDATA (NULL, UNIT_FIX + UNIT_BINK, INIMEMSIZE) };
UNIT cpu_unit = { UDATA (NULL, UNIT_FIX|UNIT_BINK, INIMEMSIZE) };
REG cpu_reg[] = {
{ ORDATA (PC, saved_PC, 16) },
@@ -533,7 +536,7 @@ REG cpu_reg[] = {
{ BRDATA (IREQ, int_req, 8, 32, IPL_HLVL), REG_RO },
{ ORDATA (TRAPS, trap_req, TRAP_V_MAX) },
{ FLDATA (WAIT, wait_state, 0) },
{ FLDATA (WAIT_ENABLE, wait_enable, 0) },
{ FLDATA (WAIT_ENABLE, wait_enable, 0), REG_HIDDEN },
{ ORDATA (STOP_TRAPS, stop_trap, TRAP_V_MAX) },
{ FLDATA (STOP_VECA, stop_vecabort, 0) },
{ FLDATA (STOP_SPA, stop_spabort, 0) },
@@ -583,6 +586,8 @@ MTAB cpu_mod[] = {
{ MTAB_XTD|MTAB_VDV, OPT_CIS, NULL, "NOCIS", &cpu_clr_opt },
{ MTAB_XTD|MTAB_VDV, OPT_MMU, NULL, "MMU", &cpu_set_opt },
{ MTAB_XTD|MTAB_VDV, OPT_MMU, NULL, "NOMMU", &cpu_clr_opt },
{ MTAB_XTD|MTAB_VDV, 0, "IDLE", "IDLE", &sim_set_idle, &sim_show_idle },
{ MTAB_XTD|MTAB_VDV, 0, NULL, "NOIDLE", &sim_clr_idle, NULL },
{ UNIT_MSIZE, 16384, NULL, "16K", &cpu_set_size},
{ UNIT_MSIZE, 32768, NULL, "32K", &cpu_set_size},
{ UNIT_MSIZE, 49152, NULL, "48K", &cpu_set_size},
@@ -786,8 +791,11 @@ while (reason == 0) {
if (tbit) setTRAP (TRAP_TRC);
if (wait_state) { /* wait state? */
if (sim_qcount () != 0) sim_interval = 0; /* force check */
else reason = STOP_WAIT;
if (sim_idle_enab) /* idle enabled? */
sim_idle (TMR_CLK, TRUE);
else if (wait_enable) /* old style idle? */
sim_interval = 0; /* force check */
else sim_interval = sim_interval - 1; /* count cycle */
continue;
}
@@ -846,7 +854,7 @@ while (reason == 0) {
else setTRAP (TRAP_ILL); /* no, ill inst */
break;
case 1: /* WAIT */
if (wait_enable) wait_state = 1;
wait_state = 1;
break;
case 3: /* BPT */
setTRAP (TRAP_BPT);
@@ -1374,7 +1382,7 @@ while (reason == 0) {
else PWriteW (dst, last_pa);
break;
/* Opcode 07: EIS, FIS (not implemented), CIS
/* Opcode 07: EIS, FIS, CIS
Notes:
- The code assumes that the host int length is at least 32 bits.
@@ -1471,7 +1479,8 @@ while (reason == 0) {
}
else if (src2 == 32) { /* [32] = -32 */
dst = -sign;
V = C = 0;
V = 0;
C = sign;
}
else { /* [33,63] = -31,-1 */
dst = (src >> (64 - src2)) | (-sign << (src2 - 32));
@@ -1505,7 +1514,7 @@ while (reason == 0) {
else if (src2 == 32) { /* [32] = -32 */
dst = -sign;
V = 0;
C = (src >> 31) & 1;
C = sign;
}
else { /* [33,63] = -31,-1 */
dst = (src >> (64 - src2)) | (-sign << (src2 - 32));
@@ -2136,7 +2145,7 @@ if ((va & 1) && CPUT (HAS_ODD)) { /* odd address? */
}
pa = relocR (va); /* relocate */
if (ADDR_IS_MEM (pa)) return (M[pa >> 1]); /* memory address? */
if ((pa < IOPAGEBASE) || /* I/O address */
if ((pa < IOPAGEBASE) || /* not I/O address */
(CPUT (CPUT_J) && (pa >= IOBA_CPU))) { /* or J11 int reg? */
setCPUERR (CPUE_NXM);
ABORT (TRAP_NXM);
@@ -2158,7 +2167,7 @@ if ((va & 1) && CPUT (HAS_ODD)) { /* odd address? */
}
pa = relocR (va); /* relocate */
if (ADDR_IS_MEM (pa)) return (M[pa >> 1]); /* memory address? */
if (pa < IOPAGEBASE) { /* I/O address? */
if (pa < IOPAGEBASE) { /* not I/O address? */
setCPUERR (CPUE_NXM);
ABORT (TRAP_NXM);
}
@@ -2175,7 +2184,7 @@ int32 pa, data;
pa = relocR (va); /* relocate */
if (ADDR_IS_MEM (pa)) return (va & 1? M[pa >> 1] >> 8: M[pa >> 1]) & 0377;
if (pa < IOPAGEBASE) { /* I/O address? */
if (pa < IOPAGEBASE) { /* not I/O address? */
setCPUERR (CPUE_NXM);
ABORT (TRAP_NXM);
}
@@ -2196,7 +2205,7 @@ if ((va & 1) && CPUT (HAS_ODD)) { /* odd address? */
}
last_pa = relocW (va); /* reloc, wrt chk */
if (ADDR_IS_MEM (last_pa)) return (M[last_pa >> 1]); /* memory address? */
if (last_pa < IOPAGEBASE) { /* I/O address? */
if (last_pa < IOPAGEBASE) { /* not I/O address? */
setCPUERR (CPUE_NXM);
ABORT (TRAP_NXM);
}
@@ -2214,7 +2223,7 @@ int32 data;
last_pa = relocW (va); /* reloc, wrt chk */
if (ADDR_IS_MEM (last_pa))
return (va & 1? M[last_pa >> 1] >> 8: M[last_pa >> 1]) & 0377;
if (last_pa < IOPAGEBASE) { /* I/O address? */
if (last_pa < IOPAGEBASE) { /* not I/O address? */
setCPUERR (CPUE_NXM);
ABORT (TRAP_NXM);
}
@@ -2247,7 +2256,7 @@ if (ADDR_IS_MEM (pa)) { /* memory address? */
M[pa >> 1] = data;
return;
}
if (pa < IOPAGEBASE) { /* I/O address? */
if (pa < IOPAGEBASE) { /* not I/O address? */
setCPUERR (CPUE_NXM);
ABORT (TRAP_NXM);
}
@@ -2268,7 +2277,7 @@ if (ADDR_IS_MEM (pa)) { /* memory address? */
else M[pa >> 1] = (M[pa >> 1] & ~0377) | data;
return;
}
if (pa < IOPAGEBASE) { /* I/O address? */
if (pa < IOPAGEBASE) { /* not I/O address? */
setCPUERR (CPUE_NXM);
ABORT (TRAP_NXM);
}
@@ -2285,7 +2294,7 @@ if (ADDR_IS_MEM (pa)) { /* memory address? */
M[pa >> 1] = data;
return;
}
if (pa < IOPAGEBASE) { /* I/O address? */
if (pa < IOPAGEBASE) { /* not I/O address? */
setCPUERR (CPUE_NXM);
ABORT (TRAP_NXM);
}
@@ -2303,7 +2312,7 @@ if (ADDR_IS_MEM (pa)) { /* memory address? */
else M[pa >> 1] = (M[pa >> 1] & ~0377) | data;
return;
}
if (pa < IOPAGEBASE) { /* I/O address? */
if (pa < IOPAGEBASE) { /* not I/O address? */
setCPUERR (CPUE_NXM);
ABORT (TRAP_NXM);
}
@@ -2574,8 +2583,8 @@ switch ((pa >> 1) & 3) { /* decode pa<2:1> */
case 3: /* MMR2 */
*data = MMR2;
break;
}
/* end switch pa */
} /* end switch pa */
return SCPE_OK;
}

View File

@@ -1024,7 +1024,7 @@ t_stat r;
for (i = 0; cnf_tab[i].dib != NULL; i++) { /* loop thru config tab */
if (((cnf_tab[i].cpum == 0) || (cpu_type & cnf_tab[i].cpum)) &&
((cnf_tab[i].optm == 0) || (cpu_opt & cnf_tab[i].optm))) {
if (r = build_ubus_tab (&cpu_dev, cnf_tab[i].dib)) /* add to dispatch tab */
if (r = build_ubus_tab (&cpu_dev, cnf_tab[i].dib)) /* add to dispatch tab */
return r;
}
}

View File

@@ -1,6 +1,6 @@
/* pdp11_cr.c: CR/CM/CD-11 card reader simulator
Copyright (c) 2005, John A. Dundas III
Copyright (c) 2005-2007, John A. Dundas III
Portions derived from work by Douglas W. Jones, jones@cs.uiowa.edu
Portions derived from work by Robert M Supnik
@@ -51,8 +51,8 @@
http://www.cs.uiowa.edu/~jones/cards/
Paul Mattes' x026 keypunch simulator
http://x3270.bgp.nu/x026.html
CDRSER.MAC - TOPS card reader driver source
http://pdp-10.trailing-edge.com/custsupcuspmar86_bb-x130b-sb/02/cdrser.mac
CD2SER.MAC - TOPS card reader driver source
http://pdp-10.trailing-edge.com/custsupcuspmar86_bb-x130b-sb/02/cd2ser.mac
The Card Image format code and documentation is adapted from Prof.
Jones's site, with his permission. Please see his site for additional
@@ -66,14 +66,13 @@
3. No testing under RSX; volunteers needed
4. No testing under Ultrix or Unix for PDP-11; volunteers needed
5. No testing under Ultrix or Unix for VAX; volunteers needed
6. No PDP-10 support; volunteers needed
7. The simulator implements a single controller/reader combination
6. The simulator implements a single controller/reader combination
Operating System Notes
RT-11 (and CTS-300) support one CR11 or CM11, but no CD11.
VMS supports multiple CR11 controllers.
VMS supports multiple CR11 controllers, but no CD11.
RSTS/E supports either the CR11/CM11 or CD11 but not both in
the same SIL. It appears to support only one unit.
@@ -84,12 +83,11 @@
Don't have any information about Unix or Ultrix-11 yet. Same
for VAX Unices.
TOPS: it appears that both the CD11 and CR11 were supported.
I don't have any knowledge on how to make this work with the
PDP-10 simulation, though.
TOPS: only the CD11 is supported, under the name CD20.
Revision History:
01-Feb-07 RMS Added PDP-10 support
12-May-06 JAD Modify the DEBUG code to use the SIMH DEBUG_x
macros. Modify the UNIT structure to include
the DEBUG bit.
@@ -168,14 +166,23 @@
#if defined (VM_PDP10) /* PDP10 version */
#include "pdp10_defs.h"
extern int32 int_req;
#define DFLT_DIS (DEV_DIS)
#define DFLT_CR11 (0) /* CD11 only */
#define DFLT_CPM 1000
#elif defined (VM_VAX) /* VAX version */
#include "vax_defs.h"
extern int32 int_req[IPL_HLVL];
#define DFLT_DIS (0)
#define DFLT_CR11 (UNIT_CR11)
#define DFLT_CPM 285
#else /* PDP-11 version */
#include "pdp11_defs.h"
extern int32 int_req[IPL_HLVL];
#define DFLT_DIS (0)
#define DFLT_CR11 (UNIT_CR11)
#define DFLT_CPM 285
#endif
extern FILE *sim_deb; /* sim_console.c */
@@ -294,7 +301,7 @@ static int32 blowerState = BLOW_OFF; /* reader vacuum/blower
static int32 spinUp = 3000; /* blower spin-up time: 3 seconds */
static int32 spinDown = 2000; /* blower spin-down time: 2 seconds */
static t_bool EOFcard = FALSE; /* played special card yet? */
static int32 cpm = 285; /* reader rate: cards per minute */
static int32 cpm = DFLT_CPM; /* reader rate: cards per minute */
/* card image in various formats */
static int16 hcard[82]; /* Hollerith format */
static char ccard[82]; /* DEC compressed format */
@@ -343,8 +350,8 @@ static DIB cr_dib = { IOBA_CR, IOLN_CR, &cr_rd, &cr_wr,
static UNIT cr_unit = {
UDATA (&cr_svc,
UNIT_ATTABLE+UNIT_SEQ+UNIT_ROABLE+UNIT_DISABLE+
UNIT_CR11+UNIT_AUTOEOF, 0),
(60 * 1000) / 285 };
DFLT_CR11+UNIT_AUTOEOF, 0),
(60 * 1000) / DFLT_CPM };
static const REG cr_reg[] = {
{ GRDATA (BUF, cr_unit.buf, DEV_RDX, 8, 0) },
@@ -367,8 +374,13 @@ static const REG cr_reg[] = {
{ NULL } };
static const MTAB cr_mod[] = {
#if defined (VM_PDP11)
{ UNIT_CR11, UNIT_CR11, "CR11", "CR11", &cr_set_type },
{ UNIT_CR11, 0, "CD11", "CD11", &cr_set_type },
#else
{ UNIT_CR11, UNIT_CR11, "CR11", NULL },
{ UNIT_CR11, 0, "CD11", NULL },
#endif
{ UNIT_AUTOEOF, UNIT_AUTOEOF, "auto EOF", "AUTOEOF", NULL },
{ UNIT_AUTOEOF, 0, "no auto EOF", "NOAUTOEOF", NULL },
/* card reader RESET switch */
@@ -395,7 +407,7 @@ DEVICE cr_dev = {
1, 10, 31, 1, DEV_RDX, 8,
NULL, NULL, &cr_reset,
NULL, &cr_attach, &cr_detach,
&cr_dib, DEV_DISABLE | DEV_UBUS | DEV_DEBUG };
&cr_dib, DEV_DISABLE | DFLT_DIS | DEV_UBUS | DEV_DEBUG };
/* Utility routines */

View File

@@ -26,6 +26,8 @@
The author gratefully acknowledges the help of Max Burnet, Megan Gentry,
and John Wilson in resolving questions about the PDP-11
16-Dec-06 RMS Added TA11 support
29-Oct-06 RMS Added clock coscheduling
06-Jul-06 RMS Added multiple KL11/DL11 support
26-Jun-06 RMS Added RF11 support
24-May-06 RMS Added 11/44 DR support (from CIS diagnostic)
@@ -569,6 +571,8 @@ typedef struct pdp_dib DIB;
#define IOLN_HK 040
#define IOBA_RF (IOPAGEBASE + 017460) /* RF11 */
#define IOLN_RF 020
#define IOBA_TA (IOPAGEBASE + 017500) /* TA11 */
#define IOLN_TA 004
#define IOBA_LPT (IOPAGEBASE + 017514) /* LP11 */
#define IOLN_LPT 004
#define IOBA_CTL (IOPAGEBASE + 017520) /* board ctrl */
@@ -613,7 +617,8 @@ typedef struct pdp_dib DIB;
#define INT_V_CLK 0 /* BR6 */
#define INT_V_PCLK 1
#define INT_V_DTA 2
#define INT_V_PIR6 3
#define INT_V_TA 3
#define INT_V_PIR6 4
#define INT_V_RK 0 /* BR5 */
#define INT_V_RL 1
@@ -653,6 +658,7 @@ typedef struct pdp_dib DIB;
#define INT_CLK (1u << INT_V_CLK)
#define INT_PCLK (1u << INT_V_PCLK)
#define INT_DTA (1u << INT_V_DTA)
#define INT_TA (1u << INT_V_TA)
#define INT_PIR6 (1u << INT_V_PIR6)
#define INT_RK (1u << INT_V_RK)
#define INT_RL (1u << INT_V_RL)
@@ -689,6 +695,7 @@ typedef struct pdp_dib DIB;
#define IPL_CLK 6 /* int pri levels */
#define IPL_PCLK 6
#define IPL_DTA 6
#define IPL_TA 6
#define IPL_RK 5
#define IPL_RL 5
#define IPL_RX 5
@@ -749,6 +756,7 @@ typedef struct pdp_dib DIB;
#define VEC_CR 0230
#define VEC_RP 0254
#define VEC_TQ 0260
#define VEC_TA 0260
#define VEC_RX 0264
#define VEC_RY 0264
#define VEC_TTIX 0300
@@ -810,4 +818,6 @@ void mba_set_don (uint32 mbus);
void mba_set_enbdis (uint32 mb, t_bool dis);
t_stat mba_show_num (FILE *st, UNIT *uptr, int32 val, void *desc);
int32 clk_cosched (int32 wait);
#endif

View File

@@ -1,6 +1,6 @@
/* pdp11_dz.c: DZ11 terminal multiplexor simulator
Copyright (c) 2001-2005, Robert M Supnik
Copyright (c) 2001-2006, Robert M Supnik
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
@@ -25,6 +25,7 @@
dz DZ11 terminal multiplexor
29-Oct-06 RMS Synced poll and clock
22-Nov-05 RMS Revised for new terminal processing routines
07-Jul-05 RMS Removed extraneous externs
15-Jun-05 RMS Revised for new autoconfigure interface
@@ -304,7 +305,8 @@ switch ((PA >> 1) & 03) { /* case on PA<2:1> */
(dz_csr[dz] & 0377) | (data << 8):
(dz_csr[dz] & ~0377) | data;
if (data & CSR_CLR) dz_clear (dz, FALSE); /* clr? reset */
if (data & CSR_MSE) sim_activate (&dz_unit, tmxr_poll);
if (data & CSR_MSE) /* MSE? start poll */
sim_activate (&dz_unit, clk_cosched (tmxr_poll));
else dz_csr[dz] &= ~(CSR_SA | CSR_RDONE | CSR_TRDY);
if ((data & CSR_RIE) == 0) dz_clr_rxint (dz); /* RIE = 0? */
else if (((dz_csr[dz] & CSR_IE) == 0) && /* RIE 0->1? */

View File

@@ -145,47 +145,55 @@
/* Double precision operations on 64b quantities */
#define F_LOAD(qd,ac,ds) ds.h = ac.h; ds.l = (qd)? ac.l: 0
#define F_LOAD_P(qd,ac,ds) ds->h = ac.h; ds->l = (qd)? ac.l: 0
#define F_LOAD_FRAC(qd,ac,ds) ds.h = (ac.h & FP_FRACH) | FP_HB; \
ds.l = (qd)? ac.l: 0
#define F_STORE(qd,sr,ac) ac.h = sr.h; if ((qd)) ac.l = sr.l
#define F_STORE_P(qd,sr,ac) ac.h = sr->h; if ((qd)) ac.l = sr->l
#define F_GET_FRAC_P(sr,ds) ds.l = sr->l; \
ds.h = (sr->h & FP_FRACH) | FP_HB
#define F_ADD(s2,s1,ds) ds.l = (s1.l + s2.l) & 0xFFFFFFFF; \
ds.h = (s1.h + s2.h + (ds.l < s2.l)) & 0xFFFFFFFF
#define F_SUB(s2,s1,ds) ds.h = (s1.h - s2.h - (s1.l < s2.l)) & 0xFFFFFFFF; \
ds.l = (s1.l - s2.l) & 0xFFFFFFFF
#define F_LT(x,y) ((x.h < y.h) || ((x.h == y.h) && (x.l < y.l)))
#define F_LT_AP(x,y) (((x->h & ~FP_SIGN) < (y->h & ~FP_SIGN)) || \
(((x->h & ~FP_SIGN) == (y->h & ~FP_SIGN)) && (x->l < y->l)))
#define F_LOAD(qd,ac,ds) \
ds.h = ac.h; ds.l = (qd)? ac.l: 0
#define F_LOAD_P(qd,ac,ds) \
ds->h = ac.h; ds->l = (qd)? ac.l: 0
#define F_LOAD_FRAC(qd,ac,ds) \
ds.h = (ac.h & FP_FRACH) | FP_HB; \
ds.l = (qd)? ac.l: 0
#define F_STORE(qd,sr,ac) \
ac.h = sr.h; if ((qd)) ac.l = sr.l
#define F_STORE_P(qd,sr,ac) \
ac.h = sr->h; if ((qd)) ac.l = sr->l
#define F_GET_FRAC_P(sr,ds) \
ds.l = sr->l; \
ds.h = (sr->h & FP_FRACH) | FP_HB
#define F_ADD(s2,s1,ds) \
ds.l = (s1.l + s2.l) & 0xFFFFFFFF; \
ds.h = (s1.h + s2.h + (ds.l < s2.l)) & 0xFFFFFFFF
#define F_SUB(s2,s1,ds) \
ds.h = (s1.h - s2.h - (s1.l < s2.l)) & 0xFFFFFFFF; \
ds.l = (s1.l - s2.l) & 0xFFFFFFFF
#define F_LT(x,y) ((x.h < y.h) || ((x.h == y.h) && (x.l < y.l)))
#define F_LT_AP(x,y) (((x->h & ~FP_SIGN) < (y->h & ~FP_SIGN)) || \
(((x->h & ~FP_SIGN) == (y->h & ~FP_SIGN)) && (x->l < y->l)))
#define F_LSH_V(sr,n,ds) \
ds.h = (((n) >= 32)? (sr.l << ((n) - 32)): \
(sr.h << (n)) | ((sr.l >> (32 - (n))) & and_mask[n])) \
& 0xFFFFFFFF; \
ds.l = ((n) >= 32)? 0: (sr.l << (n)) & 0xFFFFFFFF
ds.h = (((n) >= 32)? (sr.l << ((n) - 32)): \
(sr.h << (n)) | ((sr.l >> (32 - (n))) & and_mask[n])) \
& 0xFFFFFFFF; \
ds.l = ((n) >= 32)? 0: (sr.l << (n)) & 0xFFFFFFFF
#define F_RSH_V(sr,n,ds) \
ds.l = (((n) >= 32)? (sr.h >> ((n) - 32)) & and_mask[64 - (n)]: \
((sr.l >> (n)) & and_mask[32 - (n)]) | \
(sr.h << (32 - (n)))) & 0xFFFFFFFF; \
ds.h = ((n) >= 32)? 0: \
((sr.h >> (n)) & and_mask[32 - (n)]) & 0xFFFFFFFF
ds.l = (((n) >= 32)? (sr.h >> ((n) - 32)) & and_mask[64 - (n)]: \
((sr.l >> (n)) & and_mask[32 - (n)]) | \
(sr.h << (32 - (n)))) & 0xFFFFFFFF; \
ds.h = ((n) >= 32)? 0: \
((sr.h >> (n)) & and_mask[32 - (n)]) & 0xFFFFFFFF
/* For the constant shift macro, arguments must in the range [2,31] */
#define F_LSH_1(ds) ds.h = ((ds.h << 1) | ((ds.l >> 31) & 1)) & 0xFFFFFFFF; \
ds.l = (ds.l << 1) & 0xFFFFFFFF
#define F_RSH_1(ds) ds.l = ((ds.l >> 1) & 0x7FFFFFFF) | ((ds.h & 1) << 31); \
ds.h = ((ds.h >> 1) & 0x7FFFFFFF)
#define F_LSH_1(ds) ds.h = ((ds.h << 1) | ((ds.l >> 31) & 1)) & 0xFFFFFFFF; \
ds.l = (ds.l << 1) & 0xFFFFFFFF
#define F_RSH_1(ds) ds.l = ((ds.l >> 1) & 0x7FFFFFFF) | ((ds.h & 1) << 31); \
ds.h = ((ds.h >> 1) & 0x7FFFFFFF)
#define F_LSH_K(sr,n,ds) \
ds.h = ((sr.h << (n)) | ((sr.l >> (32 - (n))) & and_mask[n])) \
& 0xFFFFFFFF; \
ds.l = (sr.l << (n)) & 0xFFFFFFFF
ds.h = ((sr.h << (n)) | ((sr.l >> (32 - (n))) & and_mask[n])) \
& 0xFFFFFFFF; \
ds.l = (sr.l << (n)) & 0xFFFFFFFF
#define F_RSH_K(sr,n,ds) \
ds.l = (((sr.l >> (n)) & and_mask[32 - (n)]) | \
(sr.h << (32 - (n)))) & 0xFFFFFFFF; \
ds.h = ((sr.h >> (n)) & and_mask[32 - (n)]) & 0xFFFFFFFF
ds.l = (((sr.l >> (n)) & and_mask[32 - (n)]) | \
(sr.h << (32 - (n)))) & 0xFFFFFFFF; \
ds.h = ((sr.h >> (n)) & and_mask[32 - (n)]) & 0xFFFFFFFF
#define F_LSH_GUARD(ds) F_LSH_K(ds,FP_GUARD,ds)
#define F_RSH_GUARD(ds) F_RSH_K(ds,FP_GUARD,ds)
@@ -252,7 +260,8 @@ int32 i, qdouble, lenf, leni;
int32 newV, exp, sign;
fpac_t fac, fsrc, modfrac;
static const uint32 i_limit[2][2] = {
{ 0x80000000, 0x80010000 }, { 0x80000000, 0x80000001 }
{ 0x80000000, 0x80010000 },
{ 0x80000000, 0x80000001 }
};
backup_PC = PC; /* save PC for FEA */
@@ -433,7 +442,7 @@ switch ((IR >> 8) & 017) { /* decode IR<11:8> */
if (FPS & FPS_L) {
leni = LONG;
i = FP_BIAS + 32;
}
}
else {
leni = WORD;
i = FP_BIAS + 16;
@@ -602,7 +611,8 @@ return 0;
uint32 ReadI (int32 VA, int32 spec, int32 len)
{
if ((len == WORD) || (spec == 027)) return (ReadW (VA) << 16);
return ((ReadW (VA) << 16) | ReadW ((VA & ~0177777) | ((VA + 2) & 0177777)));
return ((ReadW (VA) << 16) |
ReadW ((VA & ~0177777) | ((VA + 2) & 0177777)));
}
/* Read floating operand

View File

@@ -469,7 +469,7 @@ int32 drv, i, j;
drv = GET_UNIT (hkcs2); /* get current unit */
j = (PA >> 1) & 017; /* get reg offset */
if (reg_in_drive[j] && (hk_unit[drv].flags & UNIT_DIS)) { /* nx disk */
if (reg_in_drive[j] && (hk_unit[drv].flags & UNIT_DIS)) { /* nx disk */
hkcs2 = hkcs2 | CS2_NED; /* set error flag */
update_hkcs (0, drv);
*data = 0;
@@ -705,6 +705,7 @@ switch (fnc) { /* case on function */
case FNC_NOP: /* no operation */
update_hkcs (CS1_DONE, drv); /* done */
break;
case FNC_PACK: /* pack acknowledge */
hkds[drv] = hkds[drv] | DS_VV; /* set volume valid */
update_hkcs (CS1_DONE, drv); /* done */

View File

@@ -25,6 +25,7 @@
rf RF11 fixed head disk
25-Dec-06 RMS Fixed bug in unit mask (found by John Dundas)
26-Jun-06 RMS Cloned from RF08 simulator
The RF11 is a head-per-track disk. To minimize overhead, the entire RF11
@@ -42,7 +43,7 @@
#define UNIT_V_AUTO (UNIT_V_UF + 0) /* autosize */
#define UNIT_V_PLAT (UNIT_V_UF + 1) /* #platters - 1 */
#define UNIT_M_PLAT 03
#define UNIT_M_PLAT (RF_NUMDK - 1)
#define UNIT_GETP(x) ((((x) >> UNIT_V_PLAT) & UNIT_M_PLAT) + 1)
#define UNIT_AUTO (1 << UNIT_V_AUTO)
#define UNIT_PLAT (UNIT_M_PLAT << UNIT_V_PLAT)

View File

@@ -31,12 +31,15 @@
WARNING: The interupt logic of the RH11/RH70 is unusual and must be
simulated with great precision. The RH11 has an internal interrupt
request flop, CSTB INTR, which is controlled as follows:
- Writing IE and DONE simultaneously sets CSTB INTR
- Controller clear, INIT, and interrupt acknowledge clear CSTB INTR
(and also clear IE)
- A transition of DONE from 0 to 1 sets CSTB INTR from IE
The output of CSTB INTR is OR'd with the AND of RPCS1<SC,DONE,IE> to
create the interrupt request signal. Thus,
- The DONE interrupt is edge sensitive, but the SC interrupt is
level sensitive.
- The DONE interrupt, once set, is not disabled if IE is cleared,

View File

@@ -75,7 +75,8 @@
#define RK_NUMTR (RK_NUMCY * RK_NUMSF) /* tracks/drive */
#define RK_NUMDR 8 /* drives/controller */
#define RK_M_NUMDR 07
#define RK_SIZE (RK_NUMCY * RK_NUMSF * RK_NUMSC * RK_NUMWD) /* words/drive */
#define RK_SIZE (RK_NUMCY * RK_NUMSF * RK_NUMSC * RK_NUMWD)
/* words/drive */
#define RK_CTLI 1 /* controller int */
#define RK_SCPI(x) (2u << (x)) /* drive int */
#define RK_MAXFR (1 << 16) /* max transfer */
@@ -172,8 +173,8 @@
#define RKBA_IMP 0177776 /* implemented */
#define RK_MIN 10
#define MAX(x,y) (((x) > (y))? (x): (y))
#define RK_MIN 10
#define MAX(x,y) (((x) > (y))? (x): (y))
extern uint16 *M; /* memory */
extern int32 int_req[IPL_HLVL];
@@ -297,8 +298,10 @@ switch ((PA >> 1) & 07) { /* decode PA<3:1> */
rkds = (rkds & RKDS_ID) | RKDS_RK05 | RKDS_SC_OK |
(rand () % RK_NUMSC); /* random sector */
uptr = rk_dev.units + GET_DRIVE (rkda); /* selected unit */
if (uptr->flags & UNIT_ATT) rkds = rkds | RKDS_RDY; /* attached? */
if (!sim_is_active (uptr)) rkds = rkds | RKDS_RWS; /* idle? */
if (uptr->flags & UNIT_ATT) /* attached? */
rkds = rkds | RKDS_RDY;
if (!sim_is_active (uptr)) /* idle? */
rkds = rkds | RKDS_RWS;
if (uptr->flags & UNIT_WPRT) rkds = rkds | RKDS_WLK;
if (GET_SECT (rkda) == (rkds & RKDS_SC)) rkds = rkds | RKDS_ON_SC;
*data = rkds;
@@ -356,7 +359,8 @@ switch ((PA >> 1) & 07) { /* decode PA<3:1> */
SET_INT (RK); /* set int request */
}
rkcs = (rkcs & ~RKCS_RW) | (data & RKCS_RW);
if ((rkcs & CSR_DONE) && (data & CSR_GO)) rk_go (); /* new function? */
if ((rkcs & CSR_DONE) && (data & CSR_GO)) /* new function? */
rk_go ();
return SCPE_OK;
case 3: /* RKWC */
@@ -410,8 +414,9 @@ if (uptr->flags & UNIT_DIS) { /* not present? */
rk_set_done (RKER_NXD);
return;
}
if (((uptr->flags & UNIT_ATT) == 0) || sim_is_active (uptr)) {
rk_set_done (RKER_DRE); /* not att or busy */
if (((uptr->flags & UNIT_ATT) == 0) || /* not att or busy? */
sim_is_active (uptr)) {
rk_set_done (RKER_DRE);
return;
}
if ((rkcs & RKCS_FMT) && /* format and */
@@ -419,8 +424,9 @@ if ((rkcs & RKCS_FMT) && /* format and */
rk_set_done (RKER_PGE);
return;
}
if ((func == RKCS_WRITE) && (uptr->flags & UNIT_WPRT)) {
rk_set_done (RKER_WLK); /* write and locked? */
if ((func == RKCS_WRITE) && /* write and locked? */
(uptr->flags & UNIT_WPRT)) {
rk_set_done (RKER_WLK);
return;
}
if (func == RKCS_WLK) { /* write lock? */
@@ -530,7 +536,7 @@ if (wc && (err == 0)) { /* seek ok? */
for ( ; i < wc; i++) rkxb[i] = 0; /* fill buf */
}
if (rkcs & RKCS_INH) { /* incr inhibit? */
if (t = Map_WriteW (ma, 2, &rkxb[wc - 1])) { /* store last */
if (t = Map_WriteW (ma, 2, &rkxb[wc - 1])) { /* store last */
rker = rker | RKER_NXM; /* NXM? set flag */
wc = 0; /* no transfer */
}
@@ -558,7 +564,7 @@ if (wc && (err == 0)) { /* seek ok? */
}
}
if (wc) { /* any xfer? */
awc = (wc + (RK_NUMWD - 1)) & ~(RK_NUMWD - 1); /* clr to */
awc = (wc + (RK_NUMWD - 1)) & ~(RK_NUMWD - 1); /* clr to */
for (i = wc; i < awc; i++) rkxb[i] = 0; /* end of blk */
fxwrite (rkxb, sizeof (int16), awc, uptr->fileref);
err = ferror (uptr->fileref);

View File

@@ -72,7 +72,7 @@
#define RP_NUMWD 256 /* words/sector */
#define RP_MAXFR (1 << 16) /* max transfer */
#define GET_SECTOR(x,d) ((int) fmod (sim_gtime() / ((double) (x)), \
((double) drv_tab[d].sect)))
((double) drv_tab[d].sect)))
#define RM_OF (MBA_RMASK + 1)
/* Flags in the unit flags word */

View File

@@ -369,12 +369,12 @@ switch (rx_state) { /* case on state */
break;
}
uptr->TRACK = rx_track; /* now on track */
if ((rx_sector == 0) || (rx_sector > RX_NUMSC)) { /* bad sect? */
if ((rx_sector == 0) || (rx_sector > RX_NUMSC)) { /* bad sect? */
rx_done (0, 0070); /* done, error */
break;
}
da = CALC_DA (rx_track, rx_sector); /* get disk address */
if (func == RXCS_WRDEL) rx_esr = rx_esr | RXES_DD; /* del data? */
if (func == RXCS_WRDEL) rx_esr = rx_esr | RXES_DD; /* del data? */
if (func == RXCS_READ) { /* read? */
for (i = 0; i < RX_NUMBY; i++)
rx_buf[i] = fbuf[da + i];

View File

@@ -427,7 +427,7 @@ switch (ry_state) { /* case on state */
break;
}
uptr->TRACK = ry_track; /* now on track */
if ((ry_sector == 0) || (ry_sector > RX_NUMSC)) { /* bad sect? */
if ((ry_sector == 0) || (ry_sector > RX_NUMSC)) { /* bad sect? */
ry_done (0, 0070); /* done, error */
break;
}
@@ -437,7 +437,7 @@ switch (ry_state) { /* case on state */
break;
}
da = CALC_DA (ry_track, ry_sector, bps); /* get disk address */
if (func == RYCS_WRDEL) ry_esr = ry_esr | RYES_DD; /* del data? */
if (func == RYCS_WRDEL) ry_esr = ry_esr | RYES_DD; /* del data? */
if (func == RYCS_READ) { /* read? */
for (i = 0; i < bps; i++)
rx2xb[i] = fbuf[da + i];

View File

@@ -26,6 +26,8 @@
tti,tto DL11 terminal input/output
clk KW11L (and other) line frequency clock
29-Oct-06 RMS Synced keyboard and clock
Added clock coscheduling support
05-Jul-06 RMS Added UC only support for early DOS/RSTS
22-Nov-05 RMS Revised for new terminal processing routines
22-Sep-05 RMS Fixed declarations (from Sterling Garwood)
@@ -107,7 +109,7 @@ DIB tti_dib = {
1, IVCL (TTI), VEC_TTI, { NULL }
};
UNIT tti_unit = { UDATA (&tti_svc, 0, 0), KBD_POLL_WAIT };
UNIT tti_unit = { UDATA (&tti_svc, 0, 0), 0 };
REG tti_reg[] = {
{ ORDATA (BUF, tti_unit.buf, 8) },
@@ -117,7 +119,7 @@ REG tti_reg[] = {
{ FLDATA (DONE, tti_csr, CSR_V_DONE) },
{ FLDATA (IE, tti_csr, CSR_V_IE) },
{ DRDATA (POS, tti_unit.pos, T_ADDR_W), PV_LEFT },
{ DRDATA (TIME, tti_unit.wait, 24), REG_NZ + PV_LEFT },
{ DRDATA (TIME, tti_unit.wait, 24), PV_LEFT },
{ NULL }
};
@@ -153,7 +155,7 @@ DIB tto_dib = {
1, IVCL (TTO), VEC_TTO, { NULL }
};
UNIT tto_unit = { UDATA (&tto_svc, 0, 0), SERIAL_OUT_WAIT };
UNIT tto_unit = { UDATA (&tto_svc, TT_MODE_7P, 0), SERIAL_OUT_WAIT };
REG tto_reg[] = {
{ ORDATA (BUF, tto_unit.buf, 8) },
@@ -281,7 +283,7 @@ t_stat tti_svc (UNIT *uptr)
{
int32 c;
sim_activate (uptr, uptr->wait); /* continue poll */
sim_activate (uptr, KBD_WAIT (uptr->wait, tmr_poll)); /* continue poll */
if ((c = sim_poll_kbd ()) < SCPE_KFLAG) return c; /* no char or error? */
if (c & SCPE_BREAK) uptr->buf = 0; /* break? */
else uptr->buf = sim_tt_inpcvt (c, TT_GET_MODE (uptr->flags));
@@ -298,7 +300,7 @@ t_stat tti_reset (DEVICE *dptr)
tti_unit.buf = 0;
tti_csr = 0;
CLR_INT (TTI);
sim_activate (&tti_unit, tti_unit.wait); /* activate unit */
sim_activate_abs (&tti_unit, KBD_WAIT (tti_unit.wait, tmr_poll));
return SCPE_OK;
}
@@ -404,7 +406,7 @@ t_stat clk_wr (int32 data, int32 PA, int32 access)
if (clk_fnxm) return SCPE_NXM; /* not there??? */
if (PA & 1) return SCPE_OK;
clk_csr = (clk_csr & ~CLKCSR_RW) | (data & CLKCSR_RW);
if (CPUT (HAS_LTCM) && ((data & CSR_DONE) == 0)) /* monitor bit? */
if (CPUT (HAS_LTCM) && ((data & CSR_DONE) == 0)) /* monitor bit? */
clk_csr = clk_csr & ~CSR_DONE; /* clr if zero */
if ((((clk_csr & CSR_IE) == 0) && !clk_fie) || /* unless IE+DONE */
((clk_csr & CSR_DONE) == 0)) CLR_INT (CLK); /* clr intr */
@@ -434,6 +436,16 @@ if (CPUT (CPUT_24)) clk_csr = clk_csr & ~CSR_DONE;
return clk_dib.vec;
}
/* Clock coscheduling routine */
int32 clk_cosched (int32 wait)
{
int32 t;
t = sim_is_active (&clk_unit);
return (t? t - 1: wait);
}
/* Clock reset */
t_stat clk_reset (DEVICE *dptr)

View File

@@ -23,6 +23,8 @@
used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from Robert M Supnik.
20-Dec-06 RMS Added TA11 support
12-Nov-06 RMS Fixed operand order in EIS instructions (found by W.F.J. Mueller)
14-Jul-06 RMS Reordered device list
06-Jul-06 RMS Added multiple KL11/DL11 support
26-Jun-06 RMS Added RF11 support
@@ -85,6 +87,7 @@ extern DEVICE tm_dev;
extern DEVICE tq_dev;
extern DEVICE ts_dev;
extern DEVICE tu_dev;
extern DEVICE ta_dev;
extern DEVICE xq_dev, xqb_dev;
extern DEVICE xu_dev, xub_dev;
extern UNIT cpu_unit;
@@ -141,6 +144,7 @@ DEVICE *sim_devices[] = {
&ts_dev,
&tq_dev,
&tu_dev,
&ta_dev,
&xq_dev,
&xqb_dev,
&xu_dev,
@@ -311,7 +315,7 @@ return SCPE_OK;
/* Warning: for literals, the class number MUST equal the field width!! */
#define I_V_CL 18 /* class bits */
#define I_M_CL 017 /* class mask */
#define I_M_CL 037 /* class mask */
#define I_V_NPN 0 /* no operands */
#define I_V_REG 1 /* reg */
#define I_V_SOP 2 /* operand */
@@ -328,6 +332,7 @@ return SCPE_OK;
#define I_V_DOP 13 /* double operand */
#define I_V_CCC 14 /* CC clear */
#define I_V_CCS 15 /* CC set */
#define I_V_SOPR 16 /* operand, reg */
#define I_NPN (I_V_NPN << I_V_CL)
#define I_REG (I_V_REG << I_V_CL)
#define I_3B (I_V_3B << I_V_CL)
@@ -344,12 +349,14 @@ return SCPE_OK;
#define I_DOP (I_V_DOP << I_V_CL)
#define I_CCC (I_V_CCC << I_V_CL)
#define I_CCS (I_V_CCS << I_V_CL)
#define I_SOPR (I_V_SOPR << I_V_CL)
static const int32 masks[] = {
0177777, 0177770, 0177700, 0177770,
0177700+I_D, 0177400+I_D, 0177700, 0177400,
0177400, 0177000, 0177000, 0177400,
0177400+I_D+I_L, 0170000, 0177777, 0177777
0177400+I_D+I_L, 0170000, 0177777, 0177777,
0177000
};
static const char *opcode[] = {
@@ -443,7 +450,7 @@ static const int32 opc_val[] = {
0007000+I_SOP, 0007200+I_SOP, 0007300+I_SOP,
0010000+I_DOP, 0020000+I_DOP, 0030000+I_DOP, 0040000+I_DOP,
0050000+I_DOP, 0060000+I_DOP,
0070000+I_RSOP, 0071000+I_RSOP, 0072000+I_RSOP, 0073000+I_RSOP,
0070000+I_SOPR, 0071000+I_SOPR, 0072000+I_SOPR, 0073000+I_SOPR,
0074000+I_RSOP,
0075000+I_REG, 0075010+I_REG, 0075020+I_REG, 0075030+I_REG,
0076020+I_REG,
@@ -662,7 +669,7 @@ for (i = 0; opc_val[i] >= 0; i++) { /* loop thru ops */
case I_V_BR: /* cond branch */
fprintf (of, "%s ", opcode[i]);
brdisp = (l8b + l8b + ((l8b & 0200)? 0177002: 2)) & 0177777;
if (cflag) fprintf (of, "%-o", (addr + brdisp) & 0177777);
if (cflag) fprintf (of, "%-o", (addr + brdisp) & 0177777);
else if (brdisp < 01000) fprintf (of, ".+%-o", brdisp);
else fprintf (of, ".-%-o", 0200000 - brdisp);
break;
@@ -684,6 +691,12 @@ for (i = 0; opc_val[i] >= 0; i++) { /* loop thru ops */
wd1 = fprint_spec (of, addr, dstm, val[1], cflag, TRUE);
break;
case I_V_SOPR: /* sopr */
fprintf (of, "%s ", opcode[i]);
wd1 = fprint_spec (of, addr, dstm, val[1], cflag, TRUE);
fprintf (of, ",%s", rname[srcr]);
break;
case I_V_ASOP: case I_V_ASMD: /* asop, asmd */
fprintf (of, "%s %s,", opcode[i], fname[fac]);
wd1 = fprint_spec (of, addr, dstm, val[1], cflag, TRUE);
@@ -987,13 +1000,23 @@ switch (j) { /* case on class */
cptr = get_glyph (cptr, gbuf, ','); /* get glyph */
if ((reg = get_reg (gbuf, rname, 0)) < 0) return SCPE_ARG;
val[0] = val[0] | (reg << 6); /* fall through */
case I_V_SOP: /* sop */
case I_V_SOP: /* sop */
cptr = get_glyph (cptr, gbuf, 0); /* get glyph */
if ((n1 = get_spec (gbuf, addr, 0, &spec, &val[1], cflag, TRUE)) > 0)
return SCPE_ARG;
val[0] = val[0] | spec;
break;
case I_V_SOPR: /* dop, reg */
cptr = get_glyph (cptr, gbuf, ','); /* get glyph */
if ((n1 = get_spec (gbuf, addr, 0, &spec, &val[1], cflag, TRUE)) > 0)
return SCPE_ARG;
val[0] = val[0] | spec;
cptr = get_glyph (cptr, gbuf, 0); /* get glyph */
if ((reg = get_reg (gbuf, rname, 0)) < 0) return SCPE_ARG;
val[0] = val[0] | (reg << 6);
break;
case I_V_AFOP: case I_V_ASOP: case I_V_ASMD: /* fac, (s)fop */
cptr = get_glyph (cptr, gbuf, ','); /* get glyph */
if ((reg = get_reg (gbuf, fname, 0)) < 0) return SCPE_ARG;

584
PDP11/pdp11_ta.c Normal file
View File

@@ -0,0 +1,584 @@
/* pdp11_ta.c: PDP-11 cassette tape simulator
Copyright (c) 2006, 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 ATAION OF CONTRATA, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNETAION 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.
ta TA11/TU60 cassette tape
Magnetic tapes are represented as a series of variable records
of the form:
32b byte count
byte 0
byte 1
:
byte n-2
byte n-1
32b byte count
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.
Cassette format differs in one very significant way: it has file gaps
rather than file marks. If the controller spaces or reads into a file
gap and then reverses direction, the file gap is not seen again. This
is in contrast to magnetic tapes, where the file mark is a character
sequence and is seen again if direction is reversed.
*/
#include "pdp11_defs.h"
#include "sim_tape.h"
#define TA_NUMDR 2 /* #drives */
#define FNC u3 /* unit function */
#define UST u4 /* unit status */
#define TA_SIZE 93000 /* chars/tape */
#define TA_MAXFR (TA_SIZE) /* max record lnt */
/* Control/status - TACS */
#define TACS_ERR (1 << CSR_V_ERR) /* error */
#define TACS_CRC 0040000 /* CRC */
#define TACS_BEOT 0020000 /* BOT/EOT */
#define TACS_WLK 0010000 /* write lock */
#define TACS_EOF 0004000 /* end file */
#define TACS_TIM 0002000 /* timing */
#define TACS_EMP 0001000 /* empty */
#define TACS_V_UNIT 8 /* unit */
#define TACS_M_UNIT (TA_NUMDR - 1)
#define TACS_UNIT (TACS_M_UNIT << TACS_V_UNIT)
#define TACS_TR (1 << CSR_V_DONE) /* transfer req */
#define TACS_IE (1 << CSR_V_IE) /* interrupt enable */
#define TACS_RDY 0000040 /* ready */
#define TACS_ILBS 0000020 /* start CRC */
#define TACS_V_FNC 1 /* function */
#define TACS_M_FNC 07
#define TACS_WFG 00
#define TACS_WRITE 01
#define TACS_READ 02
#define TACS_SRF 03
#define TACS_SRB 04
#define TACS_SFF 05
#define TACS_SFB 06
#define TACS_REW 07
#define TACS_2ND 010
#define TACS_3RD 030
#define TACS_FNC (TACS_M_FNC << TACS_V_FNC)
#define TACS_GO (1 << CSR_V_GO) /* go */
#define TACS_W (TACS_UNIT|TACS_IE|TACS_ILBS|TACS_FNC)
#define TACS_XFRERR (TACS_ERR|TACS_CRC|TACS_WLK|TACS_EOF|TACS_TIM)
#define GET_UNIT(x) (((x) >> TACS_V_UNIT) & TACS_M_UNIT)
#define GET_FNC(x) (((x) >> TACS_V_FNC) & TACS_M_FNC)
/* Function code flags */
#define OP_WRI 01 /* op is a write */
#define OP_REV 02 /* op is rev motion */
#define OP_FWD 04 /* op is fwd motion */
/* Unit status flags */
#define UST_REV (OP_REV) /* last op was rev */
#define UST_GAP 01 /* last op hit gap */
extern int32 int_req[IPL_HLVL];
extern FILE *sim_deb;
uint32 ta_cs = 0; /* control/status */
uint32 ta_idb = 0; /* input data buf */
uint32 ta_odb = 0; /* output data buf */
uint32 ta_write = 0; /* TU60 write flag */
uint32 ta_bptr = 0; /* buf ptr */
uint32 ta_blnt = 0; /* buf length */
int32 ta_stime = 1000; /* start time */
int32 ta_ctime = 100; /* char latency */
uint32 ta_stopioe = 1; /* stop on error */
uint8 *ta_xb = NULL; /* transfer buffer */
static uint8 ta_fnc_tab[TACS_M_FNC + 1] = {
OP_WRI|OP_FWD, OP_WRI|OP_FWD, OP_FWD, OP_REV,
OP_REV , OP_FWD, OP_FWD, 0
};
DEVICE ta_dev;
t_stat ta_rd (int32 *data, int32 PA, int32 access);
t_stat ta_wr (int32 data, int32 PA, int32 access);
t_stat ta_svc (UNIT *uptr);
t_stat ta_reset (DEVICE *dptr);
t_stat ta_attach (UNIT *uptr, char *cptr);
t_stat ta_detach (UNIT *uptr);
void ta_go (void);
t_stat ta_map_err (UNIT *uptr, t_stat st);
UNIT *ta_busy (void);
void ta_set_tr (void);
uint32 ta_updsta (UNIT *uptr);
uint32 ta_crc (uint8 *buf, uint32 cnt);
/* TA data structures
ta_dev TA device descriptor
ta_unit TA unit list
ta_reg TA register list
ta_mod TA modifier list
*/
DIB ta_dib = {
IOBA_TA, IOLN_TA, &ta_rd, &ta_wr,
1, IVCL (TA), VEC_TA, { NULL }
};
UNIT ta_unit[] = {
{ UDATA (&ta_svc, UNIT_ATTABLE+UNIT_ROABLE, TA_SIZE) },
{ UDATA (&ta_svc, UNIT_ATTABLE+UNIT_ROABLE, TA_SIZE) },
};
REG ta_reg[] = {
{ ORDATA (TACS, ta_cs, 16) },
{ ORDATA (TAIDB, ta_idb, 8) },
{ ORDATA (TAODB, ta_odb, 8) },
{ FLDATA (WRITE, ta_write, 0) },
{ FLDATA (INT, IREQ (TA), INT_V_TA) },
{ FLDATA (ERR, ta_cs, CSR_V_ERR) },
{ FLDATA (TR, ta_cs, CSR_V_DONE) },
{ FLDATA (IE, ta_cs, CSR_V_IE) },
{ DRDATA (BPTR, ta_bptr, 17) },
{ DRDATA (BLNT, ta_blnt, 17) },
{ DRDATA (STIME, ta_stime, 24), PV_LEFT + REG_NZ },
{ DRDATA (CTIME, ta_ctime, 24), PV_LEFT + REG_NZ },
{ FLDATA (STOP_IOE, ta_stopioe, 0) },
{ URDATA (UFNC, ta_unit[0].FNC, 8, 5, 0, TA_NUMDR, 0), REG_HRO },
{ URDATA (UST, ta_unit[0].UST, 8, 2, 0, TA_NUMDR, 0), REG_HRO },
{ URDATA (POS, ta_unit[0].pos, 10, T_ADDR_W, 0,
TA_NUMDR, PV_LEFT | REG_RO) },
{ ORDATA (DEVADDR, ta_dib.ba, 32), REG_HRO },
{ ORDATA (DEVVEC, ta_dib.vec, 16), REG_HRO },
{ NULL }
};
MTAB ta_mod[] = {
{ MTUF_WLK, 0, "write enabled", "WRITEENABLED", NULL },
{ MTUF_WLK, MTUF_WLK, "write locked", "LOCKED", NULL },
// { MTAB_XTD|MTAB_VUN, 0, "FORMAT", "FORMAT",
// &sim_tape_set_fmt, &sim_tape_show_fmt, NULL },
{ MTAB_XTD|MTAB_VUN, 0, "CAPACITY", NULL,
NULL, &sim_tape_show_capac, NULL },
{ MTAB_XTD|MTAB_VDV, IOLN_TA, "ADDRESS", "ADDRESS",
&set_addr, &show_addr, NULL },
{ MTAB_XTD|MTAB_VDV, 0, "VECTOR", "VECTOR",
&set_vec, &show_vec, NULL },
{ 0 }
};
DEVICE ta_dev = {
"TA", ta_unit, ta_reg, ta_mod,
TA_NUMDR, 10, 31, 1, 8, 8,
NULL, NULL, &ta_reset,
NULL, &ta_attach, &ta_detach,
&ta_dib, DEV_DISABLE | DEV_DIS | DEV_DEBUG
};
/* I/O dispatch routines, I/O addresses 17777500 - 17777503
17777500 TACS read/write
17777502 TADB read/write
*/
t_stat ta_rd (int32 *data, int32 PA, int32 access)
{
switch ((PA >> 1) & 01) { /* decode PA<1> */
case 0: /* TACSR */
*data = ta_updsta (NULL); /* update status */
break;
case 1: /* TADB */
*data = ta_idb; /* return byte */
ta_cs &= ~TACS_TR; /* clear tra req */
ta_updsta (NULL);
break;
}
return SCPE_OK;
}
t_stat ta_wr (int32 data, int32 PA, int32 access)
{
switch ((PA >> 1) & 01) { /* decode PA<1> */
case 0: /* TACS */
if (access == WRITEB) data = (PA & 1)? /* byte write? */
(ta_cs & 0377) | (data << 8): /* merge old */
(ta_cs & ~0377) | data;
ta_cs = (ta_cs & ~TACS_W) | (data & TACS_W); /* merge new */
if ((data & CSR_GO) && !ta_busy ()) /* go, not busy? */
ta_go (); /* start operation */
if (ta_cs & TACS_ILBS) ta_cs &= ~TACS_TR; /* ILBS inhibits TR */
break;
case 1: /* TADB */
if (PA & 1) break; /* ignore odd byte */
ta_odb = data; /* return byte */
ta_cs &= ~TACS_TR; /* clear tra req */
break;
} /* end switch */
ta_updsta (NULL); /* update status */
return SCPE_OK;
}
/* Start a new operation - cassette is not busy */
void ta_go (void)
{
UNIT *uptr = ta_dev.units + GET_UNIT (ta_cs);
uint32 fnc = GET_FNC (ta_cs);
uint32 flg = ta_fnc_tab[fnc];
uint32 old_ust = uptr->UST;
if (DEBUG_PRS (ta_dev)) fprintf (sim_deb,
">>TA start: op=%o, old_sta = %o, pos=%d\n",
fnc, uptr->UST, uptr->pos);
ta_cs &= ~(TACS_XFRERR|TACS_EMP|TACS_TR|TACS_RDY); /* clr err, tr, rdy */
ta_bptr = 0; /* init buffer */
ta_blnt = 0;
if ((uptr->flags & UNIT_ATT) == 0) {
ta_cs |= TACS_ERR|TACS_EMP|TACS_RDY;
return;
}
if (flg & OP_WRI) { /* write op? */
if (sim_tape_wrp (uptr)) { /* locked? */
ta_cs |= TACS_ERR|TACS_WLK|TACS_RDY; /* don't start */
return;
}
ta_odb = 0;
ta_write = 1;
}
else {
ta_idb = 0;
ta_write = 0;
}
ta_cs &= ~TACS_BEOT; /* tape in motion */
uptr->FNC = fnc; /* save function */
if ((fnc != TACS_REW) && !(flg & OP_WRI)) { /* read cmd? */
uptr->UST = flg & UST_REV; /* save direction */
if ((old_ust ^ uptr->UST) == (UST_REV|UST_GAP)) { /* reverse in gap? */
t_mtrlnt t; /* skip file mark */
if (uptr->UST) sim_tape_rdrecr (uptr, ta_xb, &t, TA_MAXFR);
else sim_tape_rdrecf (uptr, ta_xb, &t, TA_MAXFR);
if (DEBUG_PRS (ta_dev)) fprintf (sim_deb,
">>TA skip gap: op=%o, old_sta = %o, pos=%d\n",
fnc, uptr->UST, uptr->pos);
}
}
else uptr->UST = 0;
sim_activate (uptr, ta_stime); /* schedule op */
return;
}
/* Unit service */
t_stat ta_svc (UNIT *uptr)
{
uint32 i, crc;
uint32 flg = ta_fnc_tab[uptr->FNC & TACS_M_FNC];
t_mtrlnt tbc;
t_stat st, r;
if ((uptr->flags & UNIT_ATT) == 0) { /* not attached? */
ta_cs |= TACS_ERR|TACS_EMP|TACS_RDY;
ta_updsta (uptr); /* update status */
return (ta_stopioe? SCPE_UNATT: SCPE_OK);
}
if (((flg & OP_FWD) && sim_tape_eot (uptr)) || /* illegal motion? */
((flg & OP_REV) && sim_tape_bot (uptr))) {
ta_cs |= TACS_ERR|TACS_BEOT|TACS_RDY; /* error */
ta_updsta (uptr);
return SCPE_OK;
}
r = SCPE_OK;
switch (uptr->FNC) { /* case on function */
case TACS_READ: /* read start */
st = sim_tape_rdrecf (uptr, ta_xb, &ta_blnt, TA_MAXFR); /* get rec */
if (st == MTSE_RECE) ta_cs |= TACS_ERR|TACS_CRC; /* rec in err? */
else if (st != MTSE_OK) { /* other error? */
r = ta_map_err (uptr, st); /* map error */
break;
}
crc = ta_crc (ta_xb, ta_blnt); /* calculate CRC */
ta_xb[ta_blnt++] = (crc >> 8) & 0377; /* append to buffer */
ta_xb[ta_blnt++] = crc & 0377;
uptr->FNC |= TACS_2ND; /* next state */
sim_activate (uptr, ta_ctime); /* sched next char */
return SCPE_OK;
case TACS_READ|TACS_2ND: /* read char */
if (ta_bptr < ta_blnt) /* more chars? */
ta_idb = ta_xb[ta_bptr++];
else { /* no */
ta_idb = 0;
ta_cs |= TACS_ERR|TACS_CRC; /* overrun */
break; /* tape stops */
}
if (ta_cs & TACS_ILBS) { /* CRC seq? */
uptr->FNC |= TACS_3RD; /* next state */
sim_activate (uptr, ta_stime); /* sched CRC chk */
}
else {
ta_set_tr (); /* set tra req */
sim_activate (uptr, ta_ctime); /* sched next char */
}
return SCPE_OK;
case TACS_READ|TACS_3RD: /* second read CRC */
if (ta_bptr != ta_blnt) { /* partial read? */
crc = ta_crc (ta_xb, ta_bptr + 2); /* actual CRC */
if (crc != 0) ta_cs |= TACS_ERR|TACS_CRC; /* must be zero */
}
break; /* read done */
case TACS_WRITE: /* write start */
for (i = 0; i < TA_MAXFR; i++) ta_xb[i] = 0; /* clear buffer */
ta_set_tr (); /* set tra req */
uptr->FNC |= TACS_2ND; /* next state */
sim_activate (uptr, ta_ctime); /* sched next char */
return SCPE_OK;
case TACS_WRITE|TACS_2ND: /* write char */
if (ta_cs & TACS_ILBS) { /* CRC seq? */
uptr->FNC |= TACS_3RD; /* next state */
sim_activate (uptr, ta_stime); /* sched wri done */
}
else {
if ((ta_bptr < TA_MAXFR) && /* room in buf? */
((uptr->pos + ta_bptr) < uptr->capac)) /* room on tape? */
ta_xb[ta_bptr++] = ta_odb; /* store char */
ta_set_tr (); /* set tra req */
sim_activate (uptr, ta_ctime); /* sched next char */
}
return SCPE_OK;
case TACS_WRITE|TACS_3RD: /* write CRC */
if (ta_bptr) { /* anything to write? */
if (st = sim_tape_wrrecf (uptr, ta_xb, ta_bptr)) /* write, err? */
r = ta_map_err (uptr, st); /* map error */
}
break; /* op done */
case TACS_WFG: /* write file gap */
if (st = sim_tape_wrtmk (uptr)) /* write tmk, err? */
r = ta_map_err (uptr, st); /* map error */
break;
case TACS_REW: /* rewind */
sim_tape_rewind (uptr);
ta_cs |= TACS_BEOT; /* bot, no error */
break;
case TACS_SRB: /* space rev blk */
if (st = sim_tape_sprecr (uptr, &tbc)) /* space rev, err? */
r = ta_map_err (uptr, st); /* map error */
break;
case TACS_SRF: /* space rev file */
while ((st = sim_tape_sprecr (uptr, &tbc)) == MTSE_OK) ;
if (st == MTSE_TMK) /* if tape mark, */
ta_cs |= TACS_EOF; /* set EOF, no err */
else r = ta_map_err (uptr, st); /* else map error */
break;
case TACS_SFB: /* space fwd blk */
if (st = sim_tape_sprecf (uptr, &tbc)) /* space rev, err? */
r = ta_map_err (uptr, st); /* map error */
ta_cs |= TACS_CRC; /* CRC sets, no err */
break;
case TACS_SFF: /* space fwd file */
while ((st = sim_tape_sprecf (uptr, &tbc)) == MTSE_OK) ;
if (st == MTSE_TMK) /* if tape mark, */
ta_cs |= TACS_EOF; /* set EOF, no err */
else r = ta_map_err (uptr, st); /* else map error */
break;
default: /* never get here! */
return SCPE_IERR;
} /* end case */
ta_cs |= TACS_RDY; /* set ready */
ta_updsta (uptr); /* update status */
if (DEBUG_PRS (ta_dev)) fprintf (sim_deb,
">>TA done: op=%o, status = %o, pos=%d\n",
uptr->FNC, ta_cs, uptr->pos);
return r;
}
/* Update controller status */
uint32 ta_updsta (UNIT *uptr)
{
if (uptr == NULL) { /* unit specified? */
if ((uptr = ta_busy ()) == NULL) /* use busy */
uptr = ta_dev.units + GET_UNIT (ta_cs); /* use sel unit */
}
else if (ta_cs & TACS_EOF) uptr->UST |= UST_GAP; /* save EOF */
if (uptr->flags & UNIT_ATT) ta_cs &= ~TACS_EMP; /* attached? */
else ta_cs |= TACS_EMP|TACS_RDY; /* no, empty, ready */
if ((ta_cs & TACS_IE) && /* int enabled? */
(ta_cs & (TACS_TR|TACS_RDY))) /* req or ready? */
SET_INT (TA); /* set int req */
else CLR_INT (TA); /* no, clr int req */
return ta_cs;
}
/* Set transfer request */
void ta_set_tr (void)
{
if (ta_cs & TACS_TR) ta_cs |= (TACS_ERR|TACS_TIM); /* flag still set? */
else ta_cs |= TACS_TR; /* set xfr req */
if (ta_cs & TACS_IE) SET_INT (TA); /* if ie, int req */
return;
}
/* Test if controller busy */
UNIT *ta_busy (void)
{
uint32 u;
UNIT *uptr;
for (u = 0; u < TA_NUMDR; u++) { /* loop thru units */
uptr = ta_dev.units + u;
if (sim_is_active (uptr)) return uptr;
}
return NULL;
}
/* Calculate CRC on buffer */
uint32 ta_crc (uint8 *buf, uint32 cnt)
{
uint32 crc, i, j;
crc = 0;
for (i = 0; i < cnt; i++) {
crc = crc ^ (((uint32) buf[i]) << 8);
for (j = 0; j < 8; j++) {
if (crc & 1) crc = (crc >> 1) ^ 0xA001;
else crc = crc >> 1;
}
}
return crc;
}
/* Map error status */
t_stat ta_map_err (UNIT *uptr, t_stat st)
{
switch (st) {
case MTSE_FMT: /* illegal fmt */
case MTSE_UNATT: /* unattached */
ta_cs |= TACS_ERR|TACS_CRC;
case MTSE_OK: /* no error */
return SCPE_IERR; /* never get here! */
case MTSE_TMK: /* end of file */
ta_cs |= TACS_ERR|TACS_EOF;
break;
case MTSE_IOERR: /* IO error */
ta_cs |= TACS_ERR|TACS_CRC; /* set crc err */
if (ta_stopioe) return SCPE_IOERR;
break;
case MTSE_INVRL: /* invalid rec lnt */
ta_cs |= TACS_ERR|TACS_CRC; /* set crc err */
return SCPE_MTRLNT;
case MTSE_RECE: /* record in error */
case MTSE_EOM: /* end of medium */
ta_cs |= TACS_ERR|TACS_CRC; /* set crc err */
break;
case MTSE_BOT: /* reverse into BOT */
ta_cs |= TACS_ERR|TACS_BEOT; /* set bot */
break;
case MTSE_WRP: /* write protect */
ta_cs |= TACS_ERR|TACS_WLK; /* set wlk err */
break;
}
return SCPE_OK;
}
/* Reset routine */
t_stat ta_reset (DEVICE *dptr)
{
uint32 u;
UNIT *uptr;
ta_cs = 0;
ta_idb = 0;
ta_odb = 0;
ta_write = 0;
ta_bptr = 0;
ta_blnt = 0;
CLR_INT (TA); /* clear interrupt */
for (u = 0; u < TA_NUMDR; u++) { /* loop thru units */
uptr = ta_dev.units + u;
sim_cancel (uptr); /* cancel activity */
sim_tape_reset (uptr); /* reset tape */
}
if (ta_xb == NULL) ta_xb = (uint8 *) calloc (TA_MAXFR + 2, sizeof (uint8));
if (ta_xb == NULL) return SCPE_MEM;
return SCPE_OK;
}
/* Attach routine */
t_stat ta_attach (UNIT *uptr, char *cptr)
{
t_stat r;
r = sim_tape_attach (uptr, cptr);
if (r != SCPE_OK) return r;
ta_updsta (NULL);
uptr->UST = 0;
return r;
}
/* Detach routine */
t_stat ta_detach (UNIT* uptr)
{
t_stat r;
if (!(uptr->flags & UNIT_ATT)) return SCPE_OK; /* check attached */
r = sim_tape_detach (uptr);
ta_updsta (NULL);
uptr->UST = 0;
return r;
}

View File

@@ -640,7 +640,7 @@ switch (fnc) { /* case function */
case DTS_OFR: /* off reel */
if (dir) newpos = -1000; /* rev? < start */
else newpos = DTU_FWDEZ (uptr) + DT_EZLIN + 1000; /* fwd? > end */
else newpos = DTU_FWDEZ (uptr) + DT_EZLIN + 1000; /* fwd? > end */
break;
case FNC_SRCH: /* search */
@@ -811,7 +811,7 @@ switch (mot) {
return IORETURN (dt_stopoffr, STOP_DTOFF);
uptr->STATE = DTS_NXTSTA (uptr->STATE); /* advance state */
if (uptr->STATE) /* not stopped? */
sim_activate (uptr, dt_dctime - (dt_dctime >> 2)); /* reversing */
sim_activate (uptr, dt_dctime - (dt_dctime >> 2)); /* reversing */
return SCPE_OK;
case DTS_ACCF: case DTS_ACCR: /* accelerating */
@@ -1061,9 +1061,9 @@ int32 wrd = relpos / DT_WSIZE;
if (wrd == DT_BLKWD) return blk; /* fwd blknum */
if (wrd == DT_CSMWD) return 077; /* rev csum */
if (wrd == (2 * DT_HTWRD + DTU_BSIZE (uptr) - DT_CSMWD - 1)) /* fwd csum */
if (wrd == (2 * DT_HTWRD + DTU_BSIZE (uptr) - DT_CSMWD - 1)) /* fwd csum */
return (dt_csum (uptr, blk) << 12);
if (wrd == (2 * DT_HTWRD + DTU_BSIZE (uptr) - DT_BLKWD - 1)) /* rev blkno */
if (wrd == (2 * DT_HTWRD + DTU_BSIZE (uptr) - DT_BLKWD - 1)) /* rev blkno */
return dt_comobv (blk);
return 0; /* all others */
}
@@ -1107,43 +1107,43 @@ return SCPE_OK;
#define BOOT_LEN (sizeof (boot_rom) / sizeof (int16))
static const uint16 boot_rom[] = {
0042124, /* "TD" */
0012706, BOOT_START, /* MOV #boot_start, SP */
0012700, 0000000, /* MOV #unit, R0 ; unit number */
0010003, /* MOV R0, R3 */
0000303, /* SWAB R3 */
0012701, 0177342, /* MOV #TCCM, R1 ; csr */
0012702, 0004003, /* RW: MOV #4003, R2 ; rev+rnum+go */
0050302, /* BIS R3, R2 */
0010211, /* MOV R2, (R1) ; load csr */
0032711, 0100200, /* BIT #100200, (R1) ; wait */
0001775, /* BEQ .-4 */
0100370, /* BPL RW ; no err, cont */
0005761, 0177776, /* TST -2(R1) ; end zone? */
0100036, /* BPL ER ; no, err */
0012702, 0000003, /* MOV #3, R2 ; rnum+go */
0050302, /* BIS R3, R2 */
0010211, /* MOV R2, (R1) ; load csr */
0032711, 0100200, /* BIT #100200, (R1) ; wait */
0001775, /* BEQ .-4 */
0100426, /* BMI ER ; err, die */
0005761, 0000006, /* TST 6(R1) ; blk 0? */
0001023, /* BNE ER ; no, die */
0012761, 0177000, 0000002, /* MOV #-256.*2, 2(R1) ; load wc */
0005061, 0000004, /* CLR 4(R1) ; clear ba */
0012702, 0000005, /* MOV #READ+GO, R2 ; read & go */
0050302, /* BIS R3, R2 */
0010211, /* MOV R2, (R1) ; load csr */
0005002, /* CLR R2 */
0005003, /* CLR R3 */
0012704, BOOT_START+020, /* MOV #START+20, R4 */
0005005, /* CLR R5 */
0032711, 0100200, /* BIT #100200, (R1) ; wait */
0001775, /* BEQ .-4 */
0100401, /* BMI ER ; err, die */
0005007, /* CLR PC */
0012711, 0000001, /* ER: MOV #1, (R1) ; stop all */
0000000 /* HALT */
0042124, /* "TD" */
0012706, BOOT_START, /* MOV #boot_start, SP */
0012700, 0000000, /* MOV #unit, R0 ; unit number */
0010003, /* MOV R0, R3 */
0000303, /* SWAB R3 */
0012701, 0177342, /* MOV #TCCM, R1 ; csr */
0012702, 0004003, /* RW: MOV #4003, R2 ; rev+rnum+go */
0050302, /* BIS R3, R2 */
0010211, /* MOV R2, (R1) ; load csr */
0032711, 0100200, /* BIT #100200, (R1) ; wait */
0001775, /* BEQ .-4 */
0100370, /* BPL RW ; no err, cont */
0005761, 0177776, /* TST -2(R1) ; end zone? */
0100036, /* BPL ER ; no, err */
0012702, 0000003, /* MOV #3, R2 ; rnum+go */
0050302, /* BIS R3, R2 */
0010211, /* MOV R2, (R1) ; load csr */
0032711, 0100200, /* BIT #100200, (R1) ; wait */
0001775, /* BEQ .-4 */
0100426, /* BMI ER ; err, die */
0005761, 0000006, /* TST 6(R1) ; blk 0? */
0001023, /* BNE ER ; no, die */
0012761, 0177000, 0000002, /* MOV #-256.*2, 2(R1) ; load wc */
0005061, 0000004, /* CLR 4(R1) ; clear ba */
0012702, 0000005, /* MOV #READ+GO, R2 ; read & go */
0050302, /* BIS R3, R2 */
0010211, /* MOV R2, (R1) ; load csr */
0005002, /* CLR R2 */
0005003, /* CLR R3 */
0012704, BOOT_START+020, /* MOV #START+20, R4 */
0005005, /* CLR R5 */
0032711, 0100200, /* BIT #100200, (R1) ; wait */
0001775, /* BEQ .-4 */
0100401, /* BMI ER ; err, die */
0005007, /* CLR PC */
0012711, 0000001, /* ER: MOV #1, (R1) ; stop all */
0000000 /* HALT */
};
t_stat dt_boot (int32 unitno, DEVICE *dptr)
@@ -1179,7 +1179,7 @@ t_stat r;
r = attach_unit (uptr, cptr); /* attach */
if (r != SCPE_OK) return r; /* fail? */
if ((sim_switches & SIM_SW_REST) == 0) { /* not from rest? */
uptr->flags = (uptr->flags | UNIT_11FMT) & ~UNIT_8FMT; /* default 16b */
uptr->flags = (uptr->flags | UNIT_11FMT) & ~UNIT_8FMT; /* default 16b */
if (sim_switches & SWMASK ('T')) /* att 12b? */
uptr->flags = (uptr->flags | UNIT_8FMT) & ~UNIT_11FMT;
else if (sim_switches & SWMASK ('F')) /* att 18b? */

View File

@@ -118,7 +118,7 @@
#define MTC_FNC (MTC_M_FNC << MTC_V_FNC)
#define MTC_GO (1 << CSR_V_GO) /* go */
#define MTC_RW (MTC_DEN | MTC_LPAR | MTC_UNIT | MTC_IE | \
MTC_EMA | MTC_FNC)
MTC_EMA | MTC_FNC)
#define GET_EMA(x) (((x) & MTC_EMA) << (16 - MTC_V_EMA))
#define GET_UNIT(x) (((x) >> MTC_V_UNIT) & MTC_M_UNIT)
#define GET_FNC(x) (((x) >> MTC_V_FNC) & MTC_M_FNC)
@@ -422,7 +422,7 @@ if ((uptr->flags & UNIT_ATT) == 0) { /* if not attached */
}
if (DEBUG_PRS (tm_dev)) fprintf (sim_deb,
">>TM: op=%o, ma=%o, bc=%o, pos=%d\n", f, xma, cbc, uptr->pos);
">>TM: op=%o, ma=%o, bc=%o, pos=%d\n", f, xma, tm_bc, uptr->pos);
switch (f) { /* case on function */
case MTC_READ: /* read */
@@ -488,7 +488,7 @@ tm_ca = xma & 0177777; /* update mem addr */
tm_set_done (); /* set done */
tm_updcsta (uptr); /* update status */
if (DEBUG_PRS (tm_dev)) fprintf (sim_deb,
">>TM: sta=%o, ma=%o, wc=%o, pos=%d\n",
">>TM: sta=%o, ma=%o, bc=%o, pos=%d\n",
tm_sta, tm_ca, tm_bc, uptr->pos);
return r;
}

View File

@@ -653,7 +653,7 @@ switch (fnc) { /* case on function */
else tutc = tutc & ~TC_FCS;
break;
case FNC_WREOF: /* write end of file */
case FNC_WREOF: /* write end of file */
if (st = sim_tape_wrtmk (uptr)) /* write tmk, err? */
r = tu_map_err (drv, st, 0); /* map error */
break;

View File

@@ -1,6 +1,6 @@
/* pdp11_vh.c: DHQ11 asynchronous terminal multiplexor simulator
Copyright (c) 2004-2005, John A. Dundas III
Copyright (c) 2004-2006, John A. Dundas III
Portions derived from work by Robert M Supnik
Permission is hereby granted, free of charge, to any person obtaining a
@@ -26,6 +26,7 @@
vh DHQ11 asynch multiplexor for SIMH
29-Oct-06 RMS Synced poll and clock
07-Jul-05 RMS Removed extraneous externs
15-Jun-05 RMS Revised for new autoconfigure interface
Fixed bug in vector display routine
@@ -382,7 +383,7 @@ DEVICE vh_dev = {
&vh_attach, /* attach routine */
&vh_detach, /* detach routine */
(void *)&vh_dib, /* context */
DEV_FLTA | DEV_DISABLE | DEV_NET | DEV_QBUS | DEV_UBUS, /* flags */
DEV_FLTA | DEV_DISABLE | DEV_DIS |DEV_NET | DEV_QBUS | DEV_UBUS, /* flags */
};
/* Interrupt routines */
@@ -791,7 +792,7 @@ static t_stat vh_wr ( int32 data,
if (data & CSR_MASTER_RESET) {
if ((vh_unit[vh].flags & UNIT_MODEDHU) && (data & CSR_SKIP))
data &= ~CSR_MASTER_RESET;
sim_activate (&vh_unit[vh], tmxr_poll);
sim_activate (&vh_unit[vh], clk_cosched (tmxr_poll));
/* vh_mcount[vh] = 72; */ /* 1.2 seconds */
vh_mcount[vh] = MS2SIMH (1200); /* 1.2 seconds */
}

View File

@@ -66,6 +66,7 @@
Modification history:
29-Oct-06 RMS Synced poll and clock
27-Jan-06 RMS Fixed unaligned accesses in XQB (found by Doug Carman)
07-Jan-06 RMS Fixed unaligned access bugs (found by Doug Carman)
07-Sep-05 DTH Removed unused variable
@@ -209,7 +210,7 @@
#include "pdp11_xq.h"
#include "pdp11_xq_bootrom.h"
extern int32 tmr_poll, clk_tps;
extern int32 tmxr_poll;
extern FILE* sim_deb;
extern char* read_line (char *ptr, int32 size, FILE *stream);
@@ -1621,7 +1622,7 @@ t_stat xq_wr_csr(CTLR* xq, int32 data)
/* start/stop receive timer when RE transitions */
if ((xq->var->csr ^ data) & XQ_CSR_RE) {
if (data & XQ_CSR_RE)
sim_activate(&xq->unit[0], (clk_tps * tmr_poll)/xq->var->poll);
sim_activate(&xq->unit[0], clock_cosched (tmxr_poll));
else
sim_cancel(&xq->unit[0]);
}
@@ -1682,8 +1683,6 @@ t_stat xq_reset(DEVICE* dptr)
t_stat status;
CTLR* xq = xq_dev2ctlr(dptr);
const uint16 set_bits = XQ_CSR_RL | XQ_CSR_XL;
/* must be recalculated each time since tmr_poll is a dynamic number */
const int32 one_second = clk_tps * tmr_poll;
sim_debug(DBG_TRC, xq->dev, "xq_reset()\n");
@@ -1721,7 +1720,7 @@ t_stat xq_reset(DEVICE* dptr)
xq_csr_set_clr(xq, XQ_CSR_OK, 0);
/* start service timer */
sim_activate(&xq->unit[0], one_second/xq->var->poll);
sim_activate_abs(&xq->unit[0], tmxr_poll);
}
/* set hardware sanity controls */
@@ -1826,9 +1825,6 @@ t_stat xq_svc(UNIT* uptr)
{
CTLR* xq = xq_unit2ctlr(uptr);
/* must be recalculated each time since tmr_poll is a dynamic number */
const int32 one_second = clk_tps * tmr_poll;
/* if the receiver is enabled */
if (xq->var->csr & XQ_CSR_RE) {
t_stat status;
@@ -1867,7 +1863,7 @@ t_stat xq_svc(UNIT* uptr)
}
/* resubmit service timer */
sim_activate(&xq->unit[0], one_second/xq->var->poll);
sim_activate(&xq->unit[0], tmxr_poll);
return SCPE_OK;
}

View File

@@ -1,7 +1,7 @@
/* pdp11_xu.c: DEUNA/DELUA ethernet controller simulator
------------------------------------------------------------------------------
Copyright (c) 2003-2005, David T. Hittner
Copyright (c) 2003-2006, David T. Hittner
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
@@ -57,6 +57,7 @@
Modification history:
29-Oct-06 RMS Synced poll and clock
08-Dec-05 DTH Implemented ancilliary functions 022/023/024/025
18-Nov-05 DTH Corrected time between system ID packets
07-Sep-05 DTH Corrected runt packet processing (found by Tim Chapman),
@@ -83,7 +84,7 @@
#include "pdp11_xu.h"
extern int32 tmr_poll, clk_tps, cpu_astop;
extern int32 tmxr_poll, tmr_poll, clk_tps, cpu_astop;
extern FILE *sim_log;
t_stat xu_rd(int32* data, int32 PA, int32 access);
@@ -449,8 +450,8 @@ t_stat xu_svc(UNIT* uptr)
int queue_size;
t_stat status;
CTLR* xu = xu_unit2ctlr(uptr);
const int one_second = clk_tps * tmr_poll; /* recalibrate timer */
const ETH_MAC mop_multicast = {0xAB, 0x00, 0x00, 0x02, 0x00, 0x00};
const int one_second = clk_tps * tmr_poll;
/* First pump any queued packets into the system */
if ((xu->var->ReadQ.count > 0) && ((xu->var->pcsr1 & PCSR1_STATE) == STATE_RUNNING))
@@ -486,7 +487,7 @@ t_stat xu_svc(UNIT* uptr)
switch (xu->var->pcsr1 & PCSR1_STATE) {
case STATE_READY:
case STATE_RUNNING:
sim_activate(&xu->unit[0], one_second/XU_SERVICE_INTERVAL);
sim_activate(&xu->unit[0], tmxr_poll);
break;
};
@@ -522,7 +523,6 @@ void xu_setclrint(CTLR* xu, int32 bits)
t_stat xu_sw_reset (CTLR* xu)
{
t_stat status;
const int one_second = clk_tps * tmr_poll; /* recalibrate timer */
sim_debug(DBG_TRC, xu->dev, "xu_sw_reset()\n");
@@ -564,10 +564,9 @@ t_stat xu_sw_reset (CTLR* xu)
&xu->var->mac, xu->var->setup.multicast,
xu->var->setup.promiscuous);
/* activate device if not disabled - cancel first, just in case */
/* activate device if not disabled */
if ((xu->dev->flags & DEV_DIS) == 0) {
sim_cancel(&xu->unit[0]);
sim_activate(&xu->unit[0], one_second/XU_SERVICE_INTERVAL);
sim_activate_abs(&xu->unit[0], clk_cosched (tmxr_poll));
}
/* clear load_server address */
@@ -727,9 +726,9 @@ sim_debug(DBG_TRC, xu->dev, "FC_WAL: mtlen=%d\n", mtlen);
xu->var->rrlen = xu->var->udb[5];
xu->var->rxnext = 0;
xu->var->txnext = 0;
xu_dump_rxring(xu);
xu_dump_txring(xu);
/*cpu_astop=1;*/
// xu_dump_rxring(xu);
// xu_dump_txring(xu);
break;
case FC_RDCTR: /* read counters */
@@ -1072,7 +1071,7 @@ void xu_process_receive(CTLR* xu)
/* set or clear interrupt, depending on what happened */
xu_setclrint(xu, 0);
xu_dump_rxring(xu); /* debug receive ring */
// xu_dump_rxring(xu); /* debug receive ring */
}