mirror of
https://github.com/simh/simh.git
synced 2026-01-25 19:56:25 +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:
committed by
Mark Pizzolato
parent
15919a2dd7
commit
53d02f7fa7
@@ -152,10 +152,14 @@ return SCPE_OK;
|
||||
|
||||
t_stat clk_reset (DEVICE *dptr)
|
||||
{
|
||||
int32 t;
|
||||
|
||||
dev_done = dev_done & ~INT_CLK; /* clear done, int */
|
||||
int_req = int_req & ~INT_CLK;
|
||||
int_enable = int_enable & ~INT_CLK; /* clear enable */
|
||||
sim_activate (&clk_unit, clk_unit.wait); /* activate unit */
|
||||
t = sim_rtcn_init (clk_unit.wait, TMR_CLK);
|
||||
sim_activate_abs (&clk_unit, t); /* activate unit */
|
||||
tmxr_poll = t;
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* pdp8_cpu.c: PDP-8 CPU simulator
|
||||
|
||||
Copyright (c) 1993-2005, Robert M Supnik
|
||||
Copyright (c) 1993-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,8 @@
|
||||
|
||||
cpu central processor
|
||||
|
||||
30-Oct-06 RMS Added idle and infinite loop detection
|
||||
30-Sep-06 RMS Fixed SC value after DVI overflow (found by Don North)
|
||||
22-Sep-05 RMS Fixed declarations (from Sterling Garwood)
|
||||
16-Aug-05 RMS Fixed C++ declaration and cast problems
|
||||
06-Nov-04 RMS Added =n to SHOW HISTORY
|
||||
@@ -191,8 +193,9 @@
|
||||
#define PCQ_ENTRY pcq[pcq_p = (pcq_p - 1) & PCQ_MASK] = MA
|
||||
#define UNIT_V_NOEAE (UNIT_V_UF) /* EAE absent */
|
||||
#define UNIT_NOEAE (1 << UNIT_V_NOEAE)
|
||||
#define UNIT_V_MSIZE (UNIT_V_UF+1) /* dummy mask */
|
||||
#define UNIT_V_MSIZE (UNIT_V_UF + 1) /* dummy mask */
|
||||
#define UNIT_MSIZE (1 << UNIT_V_MSIZE)
|
||||
#define OP_KSF 06031 /* for idle */
|
||||
|
||||
#define HIST_PC 0x40000000
|
||||
#define HIST_MIN 64
|
||||
@@ -242,6 +245,7 @@ extern uint32 sim_brk_types, sim_brk_dflt, sim_brk_summ; /* breakpoint info */
|
||||
extern DEVICE *sim_devices[];
|
||||
extern FILE *sim_log;
|
||||
extern UNIT clk_unit, ttix_unit;
|
||||
extern t_bool sim_idle_enab;
|
||||
|
||||
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,6 +298,8 @@ REG cpu_reg[] = {
|
||||
MTAB cpu_mod[] = {
|
||||
{ UNIT_NOEAE, UNIT_NOEAE, "no EAE", "NOEAE", NULL },
|
||||
{ UNIT_NOEAE, 0, "EAE", "EAE", NULL },
|
||||
{ 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, 4096, NULL, "4K", &cpu_set_size },
|
||||
{ UNIT_MSIZE, 8192, NULL, "8K", &cpu_set_size },
|
||||
{ UNIT_MSIZE, 12288, NULL, "12K", &cpu_set_size },
|
||||
@@ -628,6 +634,7 @@ switch ((IR >> 7) & 037) { /* decode IR<0:4> */
|
||||
register and the TSC8-75 I/O flag is raised. Then the JMP is performed as usual
|
||||
(including the setting of IF, UF and clearing the interrupt inhibit flag). */
|
||||
|
||||
|
||||
case 024: /* JMP, dir, zero */
|
||||
PCQ_ENTRY;
|
||||
MA = IR & 0177; /* dir addr, page zero */
|
||||
@@ -645,6 +652,8 @@ switch ((IR >> 7) & 037) { /* decode IR<0:4> */
|
||||
PC = MA;
|
||||
break;
|
||||
|
||||
/* If JMP direct, also check for idle (KSF/JMP *-1) and infinite loop */
|
||||
|
||||
case 025: /* JMP, dir, curr */
|
||||
PCQ_ENTRY;
|
||||
MA = (MA & 007600) | (IR & 0177); /* dir addr, curr page */
|
||||
@@ -656,6 +665,20 @@ switch ((IR >> 7) & 037) { /* decode IR<0:4> */
|
||||
int_req = int_req | INT_TSC; /* request intr */
|
||||
}
|
||||
}
|
||||
if (sim_idle_enab && /* idling enabled? */
|
||||
(IF == IB)) { /* to same bank? */
|
||||
if (MA == ((PC - 2) & 07777)) { /* 1) JMP *-1? */
|
||||
if (!(int_req & (INT_ION|INT_TTI)) && /* iof, TTI flag off? */
|
||||
(M[IB|((PC - 2) & 07777)] == OP_KSF)) /* next is KSF? */
|
||||
sim_idle (TMR_CLK, FALSE); /* we're idle */
|
||||
} /* end JMP *-1 */
|
||||
else if (MA == ((PC - 1) & 07777)) { /* 2) JMP *? */
|
||||
if (!(int_req & INT_ION)) /* iof? */
|
||||
reason = STOP_LOOP; /* then infinite loop */
|
||||
else if (!(int_req & INT_ALL)) /* ion, not intr? */
|
||||
sim_idle (TMR_CLK, FALSE); /* we're idle */
|
||||
} /* end JMP */
|
||||
} /* end idle enabled */
|
||||
IF = IB; /* change IF */
|
||||
UF = UB; /* change UF */
|
||||
int_req = int_req | INT_NO_CIF_PENDING; /* clr intr inhibit */
|
||||
@@ -998,7 +1021,7 @@ switch ((IR >> 7) & 037) { /* decode IR<0:4> */
|
||||
if ((LAC & 07777) >= M[MA]) { /* overflow? */
|
||||
LAC = LAC | 010000; /* set link */
|
||||
MQ = ((MQ << 1) + 1) & 07777; /* rotate MQ */
|
||||
SC = 01; /* 1 shift */
|
||||
SC = 0; /* no shifts */
|
||||
}
|
||||
else {
|
||||
temp = ((LAC & 07777) << 12) | MQ;
|
||||
|
||||
685
PDP8/pdp8_ct.c
Normal file
685
PDP8/pdp8_ct.c
Normal file
@@ -0,0 +1,685 @@
|
||||
/* pdp8_ct.c: PDP-8 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 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.
|
||||
|
||||
ct TA8E/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.
|
||||
|
||||
Note that the read and write sequences for the cassette are asymmetric:
|
||||
|
||||
Read: KLSA /SELECT READ
|
||||
KGOA /INIT READ, CLEAR DF
|
||||
<data flag sets, char in buf>
|
||||
KGOA /READ 1ST CHAR, CLEAR DF
|
||||
DCA CHAR
|
||||
:
|
||||
<data flag sets, char in buf>
|
||||
KGOA /READ LAST CHAR, CLEAR DF
|
||||
DCA CHAR
|
||||
<data flag sets, CRC1 in buf>
|
||||
KLSA /SELECT CRC MODE
|
||||
KGOA /READ 1ST CRC
|
||||
<data flag sets, CRC2 in buf>
|
||||
KGOA /READ 2ND CRC
|
||||
<ready flag/CRC error flag sets>
|
||||
|
||||
Write: KLSA /SELECT WRITE
|
||||
TAD CHAR /1ST CHAR
|
||||
KGOA /INIT WRITE, CHAR TO BUF, CLEAR DF
|
||||
<data flag sets, char to tape>
|
||||
:
|
||||
TAD CHAR /LAST CHAR
|
||||
KGOA /CHAR TO BUF, CLEAR DF
|
||||
<data flag sets, char to tape>
|
||||
KLSA /SELECT CRC MODE
|
||||
KGOA /WRITE CRC, CLEAR DF
|
||||
<ready flag sets, CRC on tape>
|
||||
*/
|
||||
|
||||
#include "pdp8_defs.h"
|
||||
#include "sim_tape.h"
|
||||
|
||||
#define CT_NUMDR 2 /* #drives */
|
||||
#define FNC u3 /* unit function */
|
||||
#define UST u4 /* unit status */
|
||||
#define CT_MAXFR (CT_SIZE) /* max record lnt */
|
||||
#define CT_SIZE 93000 /* chars/tape */
|
||||
|
||||
/* Status Register A */
|
||||
|
||||
#define SRA_ENAB 0200 /* enable */
|
||||
#define SRA_V_UNIT 6 /* unit */
|
||||
#define SRA_M_UNIT (CT_NUMDR - 1)
|
||||
#define SRA_V_FNC 3 /* function */
|
||||
#define SRA_M_FNC 07
|
||||
#define SRA_READ 00
|
||||
#define SRA_REW 01
|
||||
#define SRA_WRITE 02
|
||||
#define SRA_SRF 03
|
||||
#define SRA_WFG 04
|
||||
#define SRA_SRB 05
|
||||
#define SRA_CRC 06
|
||||
#define SRA_SFF 07
|
||||
#define SRA_2ND 010
|
||||
#define SRA_IE 0001 /* int enable */
|
||||
#define GET_UNIT(x) (((x) >> SRA_V_UNIT) & SRA_M_UNIT)
|
||||
#define GET_FNC(x) (((x) >> SRA_V_FNC) & SRA_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 */
|
||||
|
||||
/* Status Register B, ^ = computed on the fly */
|
||||
|
||||
#define SRB_WLE 0400 /* "write lock err" */
|
||||
#define SRB_CRC 0200 /* CRC error */
|
||||
#define SRB_TIM 0100 /* timing error */
|
||||
#define SRB_BEOT 0040 /* ^BOT/EOT */
|
||||
#define SRB_EOF 0020 /* end of file */
|
||||
#define SRB_EMP 0010 /* ^drive empty */
|
||||
#define SRB_REW 0004 /* rewinding */
|
||||
#define SRB_WLK 0002 /* ^write locked */
|
||||
#define SRB_RDY 0001 /* ^ready */
|
||||
#define SRB_ALLERR (SRB_WLE|SRB_CRC|SRB_TIM|SRB_BEOT|SRB_EOF|SRB_EMP)
|
||||
#define SRB_XFRERR (SRB_WLE|SRB_CRC|SRB_TIM|SRB_EOF)
|
||||
|
||||
extern int32 int_req, stop_inst;
|
||||
extern UNIT cpu_unit;
|
||||
|
||||
uint32 ct_sra = 0; /* status reg A */
|
||||
uint32 ct_srb = 0; /* status reg B */
|
||||
uint32 ct_db = 0; /* data buffer */
|
||||
uint32 ct_df = 0; /* data flag */
|
||||
uint32 ct_write = 0; /* TU60 write flag */
|
||||
uint32 ct_bptr = 0; /* buf ptr */
|
||||
uint32 ct_blnt = 0; /* buf length */
|
||||
int32 ct_stime = 1000; /* start time */
|
||||
int32 ct_ctime = 100; /* char latency */
|
||||
uint32 ct_stopioe = 1; /* stop on error */
|
||||
uint8 *ct_xb = NULL; /* transfer buffer */
|
||||
static uint8 ct_fnc_tab[SRA_M_FNC + 1] = {
|
||||
OP_FWD, 0 , OP_WRI|OP_FWD, OP_REV,
|
||||
OP_WRI|OP_FWD, OP_REV, 0, OP_FWD
|
||||
};
|
||||
|
||||
DEVICE ct_dev;
|
||||
int32 ct70 (int32 IR, int32 AC);
|
||||
t_stat ct_svc (UNIT *uptr);
|
||||
t_stat ct_reset (DEVICE *dptr);
|
||||
t_stat ct_attach (UNIT *uptr, char *cptr);
|
||||
t_stat ct_detach (UNIT *uptr);
|
||||
t_stat ct_boot (int32 unitno, DEVICE *dptr);
|
||||
uint32 ct_updsta (UNIT *uptr);
|
||||
int32 ct_go_start (int32 AC);
|
||||
int32 ct_go_cont (UNIT *uptr, int32 AC);
|
||||
t_stat ct_map_err (UNIT *uptr, t_stat st);
|
||||
UNIT *ct_busy (void);
|
||||
void ct_set_df (t_bool timchk);
|
||||
t_bool ct_read_char (void);
|
||||
uint32 ct_crc (uint8 *buf, uint32 cnt);
|
||||
|
||||
/* CT data structures
|
||||
|
||||
ct_dev CT device descriptor
|
||||
ct_unit CT unit list
|
||||
ct_reg CT register list
|
||||
ct_mod CT modifier list
|
||||
*/
|
||||
|
||||
DIB ct_dib = { DEV_CT, 1, { &ct70 } };
|
||||
|
||||
UNIT ct_unit[] = {
|
||||
{ UDATA (&ct_svc, UNIT_ATTABLE+UNIT_ROABLE, CT_SIZE) },
|
||||
{ UDATA (&ct_svc, UNIT_ATTABLE+UNIT_ROABLE, CT_SIZE) },
|
||||
};
|
||||
|
||||
REG ct_reg[] = {
|
||||
{ ORDATA (CTSRA, ct_sra, 8) },
|
||||
{ ORDATA (CTSRB, ct_srb, 8) },
|
||||
{ ORDATA (CTDB, ct_db, 8) },
|
||||
{ FLDATA (CTDF, ct_df, 0) },
|
||||
{ FLDATA (RDY, ct_srb, 0) },
|
||||
{ FLDATA (WLE, ct_srb, 8) },
|
||||
{ FLDATA (WRITE, ct_write, 0) },
|
||||
{ FLDATA (INT, int_req, INT_V_CT) },
|
||||
{ DRDATA (BPTR, ct_bptr, 17) },
|
||||
{ DRDATA (BLNT, ct_blnt, 17) },
|
||||
{ DRDATA (STIME, ct_stime, 24), PV_LEFT + REG_NZ },
|
||||
{ DRDATA (CTIME, ct_ctime, 24), PV_LEFT + REG_NZ },
|
||||
{ FLDATA (STOP_IOE, ct_stopioe, 0) },
|
||||
{ URDATA (UFNC, ct_unit[0].FNC, 8, 4, 0, CT_NUMDR, 0), REG_HRO },
|
||||
{ URDATA (UST, ct_unit[0].UST, 8, 2, 0, CT_NUMDR, 0), REG_HRO },
|
||||
{ URDATA (POS, ct_unit[0].pos, 10, T_ADDR_W, 0,
|
||||
CT_NUMDR, PV_LEFT | REG_RO) },
|
||||
{ FLDATA (DEVNUM, ct_dib.dev, 6), REG_HRO },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
MTAB ct_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, 0, "DEVNO", "DEVNO",
|
||||
&set_dev, &show_dev, NULL },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
DEVICE ct_dev = {
|
||||
"CT", ct_unit, ct_reg, ct_mod,
|
||||
CT_NUMDR, 10, 31, 1, 8, 8,
|
||||
NULL, NULL, &ct_reset,
|
||||
&ct_boot, &ct_attach, &ct_detach,
|
||||
&ct_dib, DEV_DISABLE | DEV_DIS
|
||||
};
|
||||
|
||||
/* IOT routines */
|
||||
|
||||
int32 ct70 (int32 IR, int32 AC)
|
||||
{
|
||||
int32 srb;
|
||||
UNIT *uptr;
|
||||
|
||||
srb = ct_updsta (NULL); /* update status */
|
||||
switch (IR & 07) { /* decode IR<9:11> */
|
||||
|
||||
case 0: /* KCLR */
|
||||
ct_reset (&ct_dev); /* reset the world */
|
||||
break;
|
||||
|
||||
case 1: /* KSDR */
|
||||
if (ct_df) AC |= IOT_SKP;
|
||||
break;
|
||||
|
||||
case 2: /* KSEN */
|
||||
if (srb & SRB_ALLERR) AC |= IOT_SKP;
|
||||
break;
|
||||
|
||||
case 3: /* KSBF */
|
||||
if ((srb & SRB_RDY) && !(srb & SRB_EMP))
|
||||
AC |= IOT_SKP;
|
||||
break;
|
||||
|
||||
case 4: /* KLSA */
|
||||
ct_sra = AC & 0377;
|
||||
ct_updsta (NULL);
|
||||
return ct_sra ^ 0377;
|
||||
|
||||
case 5: /* KSAF */
|
||||
if (ct_df || (srb & (SRB_ALLERR|SRB_RDY)))
|
||||
AC |= IOT_SKP;
|
||||
break;
|
||||
|
||||
case 6: /* KGOA */
|
||||
ct_df = 0; /* clear data flag */
|
||||
if (uptr = ct_busy ()) /* op in progress? */
|
||||
AC = ct_go_cont (uptr, AC); /* yes */
|
||||
else AC = ct_go_start (AC); /* no, start */
|
||||
ct_updsta (NULL);
|
||||
break;
|
||||
|
||||
case 7: /* KSRB */
|
||||
return srb & 0377;
|
||||
} /* end switch */
|
||||
|
||||
return AC;
|
||||
}
|
||||
|
||||
/* Start a new operation - cassette is not busy */
|
||||
|
||||
int32 ct_go_start (int32 AC)
|
||||
{
|
||||
UNIT *uptr = ct_dev.units + GET_UNIT (ct_sra);
|
||||
uint32 fnc = GET_FNC (ct_sra);
|
||||
uint32 flg = ct_fnc_tab[fnc];
|
||||
uint32 old_ust = uptr->UST;
|
||||
|
||||
if ((ct_sra & SRA_ENAB) && (uptr->flags & UNIT_ATT)) { /* enabled, att? */
|
||||
ct_srb &= ~(SRB_XFRERR|SRB_REW); /* clear err, rew */
|
||||
if (flg & OP_WRI) { /* write-type op? */
|
||||
if (sim_tape_wrp (uptr)) { /* locked? */
|
||||
ct_srb |= SRB_WLE; /* set flag, abort */
|
||||
return AC;
|
||||
}
|
||||
ct_write = 1; /* set TU60 wr flag */
|
||||
ct_db = AC & 0377;
|
||||
}
|
||||
else {
|
||||
ct_write = 0;
|
||||
ct_db = 0;
|
||||
}
|
||||
if (fnc == SRA_REW) ct_srb |= SRB_REW; /* rew? set flag */
|
||||
if ((fnc != SRA_REW) && !(flg & OP_WRI)) { /* read cmd? */
|
||||
uptr->UST = flg & UST_REV; /* save direction */
|
||||
if ((old_ust ^ uptr->UST) == (UST_REV|UST_GAP)) { /* rev in gap? */
|
||||
t_mtrlnt t; /* skip tape mark */
|
||||
if (uptr->UST) sim_tape_rdrecr (uptr, ct_xb, &t, CT_MAXFR);
|
||||
else sim_tape_rdrecf (uptr, ct_xb, &t, CT_MAXFR);
|
||||
}
|
||||
}
|
||||
else uptr->UST = 0;
|
||||
ct_bptr = 0; /* init buffer */
|
||||
ct_blnt = 0;
|
||||
uptr->FNC = fnc; /* save function */
|
||||
sim_activate (uptr, ct_stime); /* schedule op */
|
||||
}
|
||||
if ((fnc == SRA_READ) || (fnc == SRA_CRC)) /* read or CRC? */
|
||||
return 0; /* get "char" */
|
||||
return AC;
|
||||
}
|
||||
|
||||
/* Continue an in-progress operation - cassette is in motion */
|
||||
|
||||
int32 ct_go_cont (UNIT *uptr, int32 AC)
|
||||
{
|
||||
int32 fnc = GET_FNC (ct_sra);
|
||||
|
||||
switch (fnc) { /* case on function */
|
||||
|
||||
case SRA_READ: /* read */
|
||||
return ct_db; /* return data */
|
||||
|
||||
case SRA_WRITE: /* write */
|
||||
ct_db = AC & 0377; /* save data */
|
||||
break;
|
||||
|
||||
case SRA_CRC: /* CRC */
|
||||
if ((uptr->FNC & SRA_M_FNC) != SRA_CRC) /* if not CRC */
|
||||
uptr->FNC = SRA_CRC; /* start CRC seq */
|
||||
if (!ct_write) return ct_db; /* read? AC <- buf */
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return AC;
|
||||
}
|
||||
|
||||
/* Unit service */
|
||||
|
||||
t_stat ct_svc (UNIT *uptr)
|
||||
{
|
||||
uint32 i, crc;
|
||||
uint32 flgs = ct_fnc_tab[uptr->FNC & SRA_M_FNC];
|
||||
t_mtrlnt tbc;
|
||||
t_stat st, r;
|
||||
|
||||
if ((uptr->flags & UNIT_ATT) == 0) { /* not attached? */
|
||||
ct_updsta (uptr); /* update status */
|
||||
return (ct_stopioe? SCPE_UNATT: SCPE_OK);
|
||||
}
|
||||
if (((flgs & OP_REV) && sim_tape_bot (uptr)) || /* rev at BOT or */
|
||||
((flgs & OP_FWD) && sim_tape_eot (uptr))) { /* fwd at EOT? */
|
||||
ct_updsta (uptr); /* op done */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
r = SCPE_OK;
|
||||
switch (uptr->FNC) { /* case on function */
|
||||
|
||||
case SRA_READ: /* read start */
|
||||
st = sim_tape_rdrecf (uptr, ct_xb, &ct_blnt, CT_MAXFR); /* get rec */
|
||||
if (st == MTSE_RECE) ct_srb |= SRB_CRC; /* rec in err? */
|
||||
else if (st != MTSE_OK) { /* other error? */
|
||||
r = ct_map_err (uptr, st); /* map error */
|
||||
break;
|
||||
}
|
||||
crc = ct_crc (ct_xb, ct_blnt); /* calculate CRC */
|
||||
ct_xb[ct_blnt++] = (crc >> 8) & 0377; /* append to buffer */
|
||||
ct_xb[ct_blnt++] = crc & 0377;
|
||||
uptr->FNC |= SRA_2ND; /* next state */
|
||||
sim_activate (uptr, ct_ctime); /* sched next char */
|
||||
return SCPE_OK;
|
||||
|
||||
case SRA_READ|SRA_2ND: /* read char */
|
||||
if (!ct_read_char ()) break; /* read, overrun? */
|
||||
ct_set_df (TRUE); /* set data flag */
|
||||
sim_activate (uptr, ct_ctime); /* sched next char */
|
||||
return SCPE_OK;
|
||||
|
||||
case SRA_WRITE: /* write start */
|
||||
for (i = 0; i < CT_MAXFR; i++) ct_xb[i] = 0; /* clear buffer */
|
||||
uptr->FNC |= SRA_2ND; /* next state */
|
||||
sim_activate (uptr, ct_ctime); /* sched next char */
|
||||
return SCPE_OK;
|
||||
|
||||
case SRA_WRITE|SRA_2ND: /* write char */
|
||||
if ((ct_bptr < CT_MAXFR) && /* room in buf? */
|
||||
((uptr->pos + ct_bptr) < uptr->capac)) /* room on tape? */
|
||||
ct_xb[ct_bptr++] = ct_db; /* store char */
|
||||
ct_set_df (TRUE); /* set data flag */
|
||||
sim_activate (uptr, ct_ctime); /* sched next char */
|
||||
return SCPE_OK;
|
||||
|
||||
case SRA_CRC: /* CRC */
|
||||
if (ct_write) { /* write? */
|
||||
if (st = sim_tape_wrrecf (uptr, ct_xb, ct_bptr)) /* write, err? */
|
||||
r = ct_map_err (uptr, st); /* map error */
|
||||
break; /* write done */
|
||||
}
|
||||
ct_read_char (); /* get second CRC */
|
||||
ct_set_df (FALSE); /* set df */
|
||||
uptr->FNC |= SRA_2ND; /* next state */
|
||||
sim_activate (uptr, ct_ctime);
|
||||
return SCPE_OK;
|
||||
|
||||
case SRA_CRC|SRA_2ND: /* second read CRC */
|
||||
if (ct_bptr != ct_blnt) { /* partial read? */
|
||||
crc = ct_crc (ct_xb, ct_bptr); /* actual CRC */
|
||||
if (crc != 0) ct_srb |= SRB_CRC; /* must be zero */
|
||||
}
|
||||
break; /* read done */
|
||||
|
||||
case SRA_WFG: /* write file gap */
|
||||
if (st = sim_tape_wrtmk (uptr)) /* write tmk, err? */
|
||||
r = ct_map_err (uptr, st); /* map error */
|
||||
break;
|
||||
|
||||
case SRA_REW: /* rewind */
|
||||
sim_tape_rewind (uptr);
|
||||
break;
|
||||
|
||||
case SRA_SRB: /* space rev blk */
|
||||
if (st = sim_tape_sprecr (uptr, &tbc)) /* space rev, err? */
|
||||
r = ct_map_err (uptr, st); /* map error */
|
||||
break;
|
||||
|
||||
case SRA_SRF: /* space rev file */
|
||||
while ((st = sim_tape_sprecr (uptr, &tbc)) == MTSE_OK) ;
|
||||
r = ct_map_err (uptr, st); /* map error */
|
||||
break;
|
||||
|
||||
case SRA_SFF: /* space fwd file */
|
||||
while ((st = sim_tape_sprecf (uptr, &tbc)) == MTSE_OK) ;
|
||||
r = ct_map_err (uptr, st); /* map error */
|
||||
break;
|
||||
|
||||
default: /* never get here! */
|
||||
return SCPE_IERR;
|
||||
} /* end case */
|
||||
|
||||
ct_updsta (uptr); /* update status */
|
||||
return r;
|
||||
}
|
||||
|
||||
/* Update controller status */
|
||||
|
||||
uint32 ct_updsta (UNIT *uptr)
|
||||
{
|
||||
int32 srb;
|
||||
|
||||
if (uptr == NULL) { /* unit specified? */
|
||||
uptr = ct_busy (); /* use busy unit */
|
||||
if ((uptr == NULL) && (ct_sra & SRA_ENAB)) /* none busy? */
|
||||
uptr = uptr = ct_dev.units + GET_UNIT (ct_sra); /* use sel unit */
|
||||
}
|
||||
else if (ct_srb & SRB_EOF) uptr->UST |= UST_GAP; /* save gap */
|
||||
if (uptr) { /* any unit? */
|
||||
ct_srb &= ~(SRB_WLK|SRB_BEOT|SRB_EMP|SRB_RDY); /* clear dyn flags */
|
||||
if ((uptr->flags & UNIT_ATT) == 0) /* unattached? */
|
||||
ct_srb = (ct_srb | SRB_EMP|SRB_WLK) & ~SRB_REW; /* empty, locked */
|
||||
if (!sim_is_active (uptr)) { /* not busy? */
|
||||
ct_srb = (ct_srb | SRB_RDY) & ~SRB_REW; /* ready, ~rew */
|
||||
if (sim_tape_bot (uptr) || sim_tape_eot (uptr)) /* update BEOT */
|
||||
ct_srb |= SRB_BEOT;
|
||||
}
|
||||
if (sim_tape_wrp (uptr) || (ct_srb & SRB_REW)) /* locked or rew? */
|
||||
ct_srb |= SRB_WLK; /* set locked */
|
||||
}
|
||||
if (ct_sra & SRA_ENAB) srb = ct_srb; /* can TA see TU60? */
|
||||
else srb = 0; /* no */
|
||||
if ((ct_sra & SRA_IE) && /* int enabled? */
|
||||
(ct_df || (srb & (SRB_ALLERR|SRB_RDY)))) /* any flag? */
|
||||
int_req |= INT_CT; /* set int req */
|
||||
else int_req &= ~INT_CT; /* no, clr int req */
|
||||
return srb;
|
||||
}
|
||||
|
||||
/* Set data flag */
|
||||
|
||||
void ct_set_df (t_bool timchk)
|
||||
{
|
||||
if (ct_df && timchk) ct_srb |= SRB_TIM; /* flag still set? */
|
||||
ct_df = 1; /* set data flag */
|
||||
if (ct_sra & SRA_IE) int_req |= INT_CT; /* if ie, int req */
|
||||
return;
|
||||
}
|
||||
|
||||
/* Read character */
|
||||
|
||||
t_bool ct_read_char (void)
|
||||
{
|
||||
if (ct_bptr < ct_blnt) { /* more chars? */
|
||||
ct_db = ct_xb[ct_bptr++];
|
||||
return TRUE;
|
||||
}
|
||||
ct_db = 0;
|
||||
ct_srb |= SRB_CRC; /* overrun */
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Test if controller busy */
|
||||
|
||||
UNIT *ct_busy (void)
|
||||
{
|
||||
uint32 u;
|
||||
UNIT *uptr;
|
||||
|
||||
for (u = 0; u < CT_NUMDR; u++) { /* loop thru units */
|
||||
uptr = ct_dev.units + u;
|
||||
if (sim_is_active (uptr)) return uptr;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Calculate CRC on buffer */
|
||||
|
||||
uint32 ct_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 ct_map_err (UNIT *uptr, t_stat st)
|
||||
{
|
||||
switch (st) {
|
||||
|
||||
case MTSE_FMT: /* illegal fmt */
|
||||
case MTSE_UNATT: /* unattached */
|
||||
ct_srb |= SRB_CRC;
|
||||
case MTSE_OK: /* no error */
|
||||
return SCPE_IERR; /* never get here! */
|
||||
|
||||
case MTSE_TMK: /* end of file */
|
||||
ct_srb |= SRB_EOF;
|
||||
break;
|
||||
|
||||
case MTSE_IOERR: /* IO error */
|
||||
ct_srb |= SRB_CRC; /* set crc err */
|
||||
if (ct_stopioe) return SCPE_IOERR;
|
||||
break;
|
||||
|
||||
case MTSE_INVRL: /* invalid rec lnt */
|
||||
ct_srb |= SRB_CRC; /* set crc err */
|
||||
return SCPE_MTRLNT;
|
||||
|
||||
case MTSE_RECE: /* record in error */
|
||||
case MTSE_EOM: /* end of medium */
|
||||
ct_srb |= SRB_CRC; /* set crc err */
|
||||
break;
|
||||
|
||||
case MTSE_BOT: /* reverse into BOT */
|
||||
break;
|
||||
|
||||
case MTSE_WRP: /* write protect */
|
||||
ct_srb |= SRB_WLE; /* set wlk err */
|
||||
break;
|
||||
}
|
||||
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Reset routine */
|
||||
|
||||
t_stat ct_reset (DEVICE *dptr)
|
||||
{
|
||||
uint32 u;
|
||||
UNIT *uptr;
|
||||
|
||||
ct_sra = 0;
|
||||
ct_srb = 0;
|
||||
ct_df = 0;
|
||||
ct_db = 0;
|
||||
ct_write = 0;
|
||||
ct_bptr = 0;
|
||||
ct_blnt = 0;
|
||||
int_req = int_req & ~INT_CT; /* clear interrupt */
|
||||
for (u = 0; u < CT_NUMDR; u++) { /* loop thru units */
|
||||
uptr = ct_dev.units + u;
|
||||
sim_cancel (uptr); /* cancel activity */
|
||||
sim_tape_reset (uptr); /* reset tape */
|
||||
}
|
||||
if (ct_xb == NULL) ct_xb = (uint8 *) calloc (CT_MAXFR + 2, sizeof (uint8));
|
||||
if (ct_xb == NULL) return SCPE_MEM;
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Attach routine */
|
||||
|
||||
t_stat ct_attach (UNIT *uptr, char *cptr)
|
||||
{
|
||||
t_stat r;
|
||||
|
||||
r = sim_tape_attach (uptr, cptr);
|
||||
if (r != SCPE_OK) return r;
|
||||
ct_updsta (NULL);
|
||||
uptr->UST = 0;
|
||||
return r;
|
||||
}
|
||||
|
||||
/* Detach routine */
|
||||
|
||||
t_stat ct_detach (UNIT* uptr)
|
||||
{
|
||||
t_stat r;
|
||||
|
||||
if (!(uptr->flags & UNIT_ATT)) return SCPE_OK; /* check attached */
|
||||
r = sim_tape_detach (uptr);
|
||||
ct_updsta (NULL);
|
||||
uptr->UST = 0;
|
||||
return r;
|
||||
}
|
||||
|
||||
/* Bootstrap routine */
|
||||
|
||||
#define BOOT_START 04000
|
||||
#define BOOT_LEN (sizeof (boot_rom) / sizeof (int16))
|
||||
|
||||
static const uint16 boot_rom[] = {
|
||||
01237, /* BOOT, TAD M50 /change CRC to REW */
|
||||
01206, /* CRCCHK, TAD L260 /crc op */
|
||||
06704, /* KLSA /load op */
|
||||
06706, /* KGOA /start */
|
||||
06703, /* KSBF /ready? */
|
||||
05204, /* RDCOD, JMP .-1 /loop */
|
||||
07264, /* L260, CML STA RAL /L = 1, AC = halt */
|
||||
06702, /* KSEN /error? */
|
||||
07610, /* SKP CLA /halt on any error */
|
||||
03211, /* DCA . /except REW or FFG */
|
||||
03636, /* DCA I PTR /TAD I PTR mustn't change L */
|
||||
01205, /* TAD RDCOD /read op */
|
||||
06704, /* KLSA /load op */
|
||||
06706, /* KGOA /start */
|
||||
06701, /* LOOP, KSDF /data ready? */
|
||||
05216, /* JMP .-1 /loop */
|
||||
07002, /* BSW /to upper 6b */
|
||||
07430, /* SZL /second byte? */
|
||||
01636, /* TAD I PTR /yes */
|
||||
07022, /* CML BSW /swap back */
|
||||
03636, /* DCA I PTR /store in mem */
|
||||
07420, /* SNL /done with both bytes? */
|
||||
02236, /* ISZ PTR /yes, bump mem ptr */
|
||||
02235, /* ISZ KNT /done with record? */
|
||||
05215, /* JMP LOOP /next byte */
|
||||
07346, /* STA CLL RTL */
|
||||
07002, /* BSW /AC = 7757 */
|
||||
03235, /* STA KNT /now read 200 byte record */
|
||||
05201, /* JMP CRCCHK /go check CRC */
|
||||
07737, /* KNT, 7737 /1's compl of byte count */
|
||||
03557, /* PTR, 3557 /load point */
|
||||
07730, /* M50, 7730 /CLA SPA SZL */
|
||||
};
|
||||
|
||||
t_stat ct_boot (int32 unitno, DEVICE *dptr)
|
||||
{
|
||||
int32 i;
|
||||
extern int32 saved_PC;
|
||||
extern uint16 M[];
|
||||
|
||||
if ((ct_dib.dev != DEV_CT) || unitno) /* only std devno */
|
||||
return STOP_NOTSTD;
|
||||
for (i = 0; i < BOOT_LEN; i++) M[BOOT_START + i] = boot_rom[i];
|
||||
saved_PC = BOOT_START;
|
||||
return SCPE_OK;
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
/* pdp8_defs.h: PDP-8 simulator definitions
|
||||
|
||||
Copyright (c) 1993-2005, Robert M Supnik
|
||||
Copyright (c) 1993-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"),
|
||||
@@ -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.
|
||||
|
||||
13-Dec-06 RMS Added TA8E support
|
||||
30-Oct-06 RMS Added infinite loop stop
|
||||
13-Oct-03 RMS Added TSC8-75 support
|
||||
04-Oct-02 RMS Added variable device number support
|
||||
20-Jan-02 RMS Fixed bug in TTx interrupt enable initialization
|
||||
@@ -50,6 +52,7 @@
|
||||
#define STOP_IBKPT 3 /* breakpoint */
|
||||
#define STOP_NOTSTD 4 /* non-std devno */
|
||||
#define STOP_DTOFF 5 /* DECtape off reel */
|
||||
#define STOP_LOOP 6 /* infinite loop */
|
||||
|
||||
/* Memory */
|
||||
|
||||
@@ -96,6 +99,7 @@ typedef struct {
|
||||
#define DEV_RL 060 /* RL8A */
|
||||
#define DEV_LPT 066 /* line printer */
|
||||
#define DEV_MT 070 /* TM8E */
|
||||
#define DEV_CT 070 /* TA8E */
|
||||
#define DEV_RK 074 /* RK8E */
|
||||
#define DEV_RX 075 /* RX8E/RX28 */
|
||||
#define DEV_DTA 076 /* TC08 */
|
||||
@@ -146,10 +150,11 @@ typedef struct {
|
||||
#define INT_V_MT (INT_V_DIRECT+4) /* TM8E */
|
||||
#define INT_V_DTA (INT_V_DIRECT+5) /* TC08 */
|
||||
#define INT_V_RL (INT_V_DIRECT+6) /* RL8A */
|
||||
#define INT_V_PWR (INT_V_DIRECT+7) /* power int */
|
||||
#define INT_V_UF (INT_V_DIRECT+8) /* user int */
|
||||
#define INT_V_TSC (INT_V_DIRECT+9) /* TSC8-75 int */
|
||||
#define INT_V_OVHD (INT_V_DIRECT+10) /* overhead start */
|
||||
#define INT_V_CT (INT_V_DIRECT+7) /* TA8E int */
|
||||
#define INT_V_PWR (INT_V_DIRECT+8) /* power int */
|
||||
#define INT_V_UF (INT_V_DIRECT+9) /* user int */
|
||||
#define INT_V_TSC (INT_V_DIRECT+10) /* TSC8-75 int */
|
||||
#define INT_V_OVHD (INT_V_DIRECT+11) /* overhead start */
|
||||
#define INT_V_NO_ION_PENDING (INT_V_OVHD+0) /* ion pending */
|
||||
#define INT_V_NO_CIF_PENDING (INT_V_OVHD+1) /* cif pending */
|
||||
#define INT_V_ION (INT_V_OVHD+2) /* interrupts on */
|
||||
@@ -175,6 +180,7 @@ typedef struct {
|
||||
#define INT_MT (1 << INT_V_MT)
|
||||
#define INT_DTA (1 << INT_V_DTA)
|
||||
#define INT_RL (1 << INT_V_RL)
|
||||
#define INT_CT (1 << INT_V_CT)
|
||||
#define INT_PWR (1 << INT_V_PWR)
|
||||
#define INT_UF (1 << INT_V_UF)
|
||||
#define INT_TSC (1 << INT_V_TSC)
|
||||
@@ -184,8 +190,8 @@ typedef struct {
|
||||
#define INT_DEV_ENABLE ((1 << INT_V_DIRECT) - 1) /* devices w/enables */
|
||||
#define INT_ALL ((1 << INT_V_OVHD) - 1) /* all interrupts */
|
||||
#define INT_INIT_ENABLE (INT_TTI+INT_TTO+INT_PTR+INT_PTP+INT_LPT) | \
|
||||
(INT_TTI1+INT_TTI2+INT_TTI3+INT_TTI4) | \
|
||||
(INT_TTO1+INT_TTO2+INT_TTO3+INT_TTO4)
|
||||
(INT_TTI1+INT_TTI2+INT_TTI3+INT_TTI4) | \
|
||||
(INT_TTO1+INT_TTO2+INT_TTO3+INT_TTO4)
|
||||
#define INT_PENDING (INT_ION+INT_NO_CIF_PENDING+INT_NO_ION_PENDING)
|
||||
#define INT_UPDATE ((int_req & ~INT_DEV_ENABLE) | (dev_done & int_enable))
|
||||
|
||||
|
||||
@@ -827,7 +827,7 @@ switch (fnc) { /* at speed, check fnc *
|
||||
Wc ovf, start of block - schedule end zone
|
||||
*/
|
||||
|
||||
case FNC_WRIT: /* write */
|
||||
case FNC_WRIT: /* write */
|
||||
wrd = DT_LIN2WD (uptr->pos, uptr); /* get word # */
|
||||
switch (dt_substate) { /* case on substate */
|
||||
|
||||
|
||||
@@ -42,7 +42,8 @@
|
||||
#define RK_NUMSF 2 /* surfaces/cylinder */
|
||||
#define RK_NUMCY 203 /* cylinders/drive */
|
||||
#define RK_NUMWD 256 /* words/sector */
|
||||
#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_NUMDR 4 /* drives/controller */
|
||||
#define RK_M_NUMDR 03
|
||||
|
||||
@@ -72,7 +73,7 @@
|
||||
#define RKS_DLT 00004 /* data late error */
|
||||
#define RKS_STAT 00002 /* drive status error */
|
||||
#define RKS_CYL 00001 /* cyl address error */
|
||||
#define RKS_ERR (RKS_BUSY+RKS_TMO+RKS_WLK+RKS_CRC+RKS_DLT+RKS_STAT+RKS_CYL)
|
||||
#define RKS_ERR (RKS_BUSY+RKS_TMO+RKS_WLK+RKS_CRC+RKS_DLT+RKS_STAT+RKS_CYL)
|
||||
|
||||
/* Command register */
|
||||
|
||||
@@ -116,12 +117,12 @@
|
||||
#define RKX_CLD 2 /* clear drive */
|
||||
#define RKX_CLSA 3 /* clear status alt */
|
||||
|
||||
#define RK_INT_UPDATE \
|
||||
if (((rk_sta & (RKS_DONE + RKS_ERR)) != 0) && \
|
||||
((rk_cmd & RKC_IE) != 0)) int_req = int_req | INT_RK; \
|
||||
else int_req = int_req & ~INT_RK
|
||||
#define RK_MIN 10
|
||||
#define MAX(x,y) (((x) > (y))? (x): (y))
|
||||
#define RK_INT_UPDATE if (((rk_sta & (RKS_DONE + RKS_ERR)) != 0) && \
|
||||
((rk_cmd & RKC_IE) != 0)) \
|
||||
int_req = int_req | INT_RK; \
|
||||
else int_req = int_req & ~INT_RK
|
||||
#define RK_MIN 10
|
||||
#define MAX(x,y) (((x) > (y))? (x): (y))
|
||||
|
||||
extern uint16 M[];
|
||||
extern int32 int_req, stop_inst;
|
||||
|
||||
131
PDP8/pdp8_sys.c
131
PDP8/pdp8_sys.c
@@ -1,6 +1,6 @@
|
||||
/* pdp8_sys.c: PDP-8 simulator interface
|
||||
|
||||
Copyright (c) 1993-2005, Robert M Supnik
|
||||
Copyright (c) 1993-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"),
|
||||
@@ -23,6 +23,9 @@
|
||||
used in advertising or otherwise to promote the sale, use or other dealings
|
||||
in this Software without prior written authorization from Robert M Supnik.
|
||||
|
||||
15-Dec-06 RMS Added TA8E support, IOT disambiguation
|
||||
30-Oct-06 RMS Added infinite loop stop
|
||||
18-Oct-06 RMS Re-ordered device list
|
||||
17-Oct-03 RMS Added TSC8-75, TD8E support, DECtape off reel message
|
||||
25-Apr-03 RMS Revised for extended file support
|
||||
30-Dec-01 RMS Revised for new TTX
|
||||
@@ -52,7 +55,7 @@ extern DEVICE rk_dev, rl_dev;
|
||||
extern DEVICE rx_dev;
|
||||
extern DEVICE df_dev, rf_dev;
|
||||
extern DEVICE dt_dev, td_dev;
|
||||
extern DEVICE mt_dev;
|
||||
extern DEVICE mt_dev, ct_dev;
|
||||
extern DEVICE ttix_dev, ttox_dev;
|
||||
extern REG cpu_reg[];
|
||||
extern uint16 M[];
|
||||
@@ -78,13 +81,13 @@ int32 sim_emax = 4;
|
||||
DEVICE *sim_devices[] = {
|
||||
&cpu_dev,
|
||||
&tsc_dev,
|
||||
&clk_dev,
|
||||
&ptr_dev,
|
||||
&ptp_dev,
|
||||
&tti_dev,
|
||||
&tto_dev,
|
||||
&ttix_dev,
|
||||
&ttox_dev,
|
||||
&clk_dev,
|
||||
&lpt_dev,
|
||||
&rk_dev,
|
||||
&rl_dev,
|
||||
@@ -94,6 +97,7 @@ DEVICE *sim_devices[] = {
|
||||
&dt_dev,
|
||||
&td_dev,
|
||||
&mt_dev,
|
||||
&ct_dev,
|
||||
NULL
|
||||
};
|
||||
|
||||
@@ -103,9 +107,23 @@ const char *sim_stop_messages[] = {
|
||||
"HALT instruction",
|
||||
"Breakpoint",
|
||||
"Non-standard device number",
|
||||
"DECtape off reel"
|
||||
"DECtape off reel",
|
||||
"Infinite loop"
|
||||
};
|
||||
|
||||
/* Ambiguous device list - these devices have overlapped IOT codes */
|
||||
|
||||
DEVICE *amb_dev[] = {
|
||||
&rl_dev,
|
||||
&ct_dev,
|
||||
&td_dev,
|
||||
NULL
|
||||
};
|
||||
|
||||
#define AMB_RL (1 << 12)
|
||||
#define AMB_CT (2 << 12)
|
||||
#define AMB_TD (3 << 12)
|
||||
|
||||
/* Binary loader
|
||||
|
||||
Two loader formats are supported: RIM loader (-r) and BIN (-b) loader.
|
||||
@@ -213,6 +231,7 @@ return SCPE_FMT; /* eof? error */
|
||||
#define I_V_OP1 4 /* operate 1 */
|
||||
#define I_V_OP2 5 /* operate 2 */
|
||||
#define I_V_OP3 6 /* operate 3 */
|
||||
#define I_V_IOA 7 /* ambiguous IOT */
|
||||
#define I_NPN (I_V_NPN << I_V_FL)
|
||||
#define I_FLD (I_V_FLD << I_V_FL)
|
||||
#define I_MRF (I_V_MRF << I_V_FL)
|
||||
@@ -220,48 +239,55 @@ return SCPE_FMT; /* eof? error */
|
||||
#define I_OP1 (I_V_OP1 << I_V_FL)
|
||||
#define I_OP2 (I_V_OP2 << I_V_FL)
|
||||
#define I_OP3 (I_V_OP3 << I_V_FL)
|
||||
#define I_IOA (I_V_IOA << I_V_FL)
|
||||
|
||||
static const int32 masks[] = {
|
||||
07777, 07707, 07000, 07000,
|
||||
07416, 07571, 017457
|
||||
07416, 07571, 017457, 077777,
|
||||
};
|
||||
|
||||
/* Ambiguous device mnemonics must precede default mnemonics */
|
||||
|
||||
static const char *opcode[] = {
|
||||
"SKON", "ION", "IOF", "SRQ",
|
||||
"SKON", "ION", "IOF", "SRQ", /* std IOTs */
|
||||
"GTF", "RTF", "SGT", "CAF",
|
||||
"RPE", "RSF", "RRB", "RFC", "RFC RRB",
|
||||
"RPE", "RSF", "RRB", "RFC", "RFC RRB", /* reader/punch */
|
||||
"PCE", "PSF", "PCF", "PPC", "PLS",
|
||||
"KCF", "KSF", "KCC", "KRS", "KIE", "KRB",
|
||||
"KCF", "KSF", "KCC", "KRS", "KIE", "KRB", /* console */
|
||||
"TLF", "TSF", "TCF", "TPC", "SPI", "TLS",
|
||||
"SBE", "SPL", "CAL",
|
||||
"CLEI", "CLDI", "CLSC", "CLLE", "CLCL", "CLSK",
|
||||
"CINT", "RDF", "RIF", "RIB",
|
||||
"SBE", "SPL", "CAL", /* power fail */
|
||||
"CLEI", "CLDI", "CLSC", "CLLE", "CLCL", "CLSK", /* clock */
|
||||
"CINT", "RDF", "RIF", "RIB", /* mem mmgt */
|
||||
"RMF", "SINT", "CUF", "SUF",
|
||||
"ADCL", "ADLM", "ADST", "ADRB",
|
||||
"RLDC", "RLSD", "RLMA", "RLCA", /* RL - ambiguous */
|
||||
"RLCB", "RLSA", "RLWC",
|
||||
"RRER", "RRWC", "RRCA", "RRCB",
|
||||
"RRSA", "RRSI", "RLSE",
|
||||
"KCLR", "KSDR", "KSEN", "KSBF", /* CT - ambiguous */
|
||||
"KLSA", "KSAF", "KGOA", "KRSB",
|
||||
"SDSS", "SDST", "SDSQ", /* TD - ambiguous */
|
||||
"SDLC", "SDLD", "SDRC", "SDRD",
|
||||
"ADCL", "ADLM", "ADST", "ADRB", /* A/D */
|
||||
"ADSK", "ADSE", "ADLE", "ADRS",
|
||||
"DCMA", "DMAR", "DMAW",
|
||||
"DCMA", "DMAR", "DMAW", /* DF/RF */
|
||||
"DCIM", "DSAC", "DIML", "DIMA",
|
||||
"DCEA", "DEAL", "DEAC",
|
||||
"DFSE", "DFSC", "DISK", "DMAC",
|
||||
"DCXA", "DXAL", "DXAC",
|
||||
"PSKF", "PCLF", "PSKE",
|
||||
"PSKF", "PCLF", "PSKE", /* LPT */
|
||||
"PSTB", "PSIE", "PCLF PSTB", "PCIE",
|
||||
"LWCR", "CWCR", "LCAR",
|
||||
"LWCR", "CWCR", "LCAR", /* MT */
|
||||
"CCAR", "LCMR", "LFGR", "LDBR",
|
||||
"RWCR", "CLT", "RCAR",
|
||||
"RMSR", "RCMR", "RFSR", "RDBR",
|
||||
"SKEF", "SKCB", "SKJD", "SKTR", "CLF",
|
||||
"DSKP", "DCLR", "DLAG",
|
||||
"DSKP", "DCLR", "DLAG", /* RK */
|
||||
"DLCA", "DRST", "DLDC", "DMAN",
|
||||
"LCD", "XDR", "STR",
|
||||
"LCD", "XDR", "STR", /* RX */
|
||||
"SER", "SDN", "INTR", "INIT",
|
||||
"DTRA", "DTCA", "DTXA", "DTLA",
|
||||
"DTRA", "DTCA", "DTXA", "DTLA", /* DT */
|
||||
"DTSF", "DTRB", "DTLB",
|
||||
"RLDC", "RLSD", "RLMA", "RLCA",
|
||||
"RLCB", "RLSA", "RLWC",
|
||||
"RRER", "RRWC", "RRCA", "RRCB",
|
||||
"RRSA", "RRSI", "RLSE",
|
||||
"ETDS", "ESKP", "ECTF", "ECDF",
|
||||
"ETDS", "ESKP", "ECTF", "ECDF", /* TSC75 */
|
||||
"ERTB", "ESME", "ERIOT", "ETEN",
|
||||
|
||||
"CDF", "CIF", "CIF CDF",
|
||||
@@ -297,31 +323,35 @@ static const int32 opc_val[] = {
|
||||
06131+I_NPN, 06132+I_NPN, 06133+I_NPN, 06135+I_NPN, 06136+I_NPN, 06137+I_NPN,
|
||||
06204+I_NPN, 06214+I_NPN, 06224+I_NPN, 06234+I_NPN,
|
||||
06244+I_NPN, 06254+I_NPN, 06264+I_NPN, 06274+I_NPN,
|
||||
06530+I_NPN, 06531+I_NPN, 06532+I_NPN, 06533+I_NPN,
|
||||
06600+I_IOA+AMB_RL, 06601+I_IOA+AMB_RL, 06602+I_IOA+AMB_RL, 06603+I_IOA+AMB_RL,
|
||||
06604+I_IOA+AMB_RL, 06605+I_IOA+AMB_RL, 06607+I_IOA+AMB_RL,
|
||||
06610+I_IOA+AMB_RL, 06611+I_IOA+AMB_RL, 06612+I_IOA+AMB_RL, 06613+I_IOA+AMB_RL,
|
||||
06614+I_IOA+AMB_RL, 06615+I_IOA+AMB_RL, 06617+I_IOA+AMB_RL,
|
||||
06700+I_IOA+AMB_CT, 06701+I_IOA+AMB_CT, 06702+I_IOA+AMB_CT, 06703+I_IOA+AMB_CT,
|
||||
06704+I_IOA+AMB_CT, 06705+I_IOA+AMB_CT, 06706+I_IOA+AMB_CT, 06707+I_IOA+AMB_CT,
|
||||
06771+I_IOA+AMB_TD, 06772+I_IOA+AMB_TD, 06773+I_IOA+AMB_TD,
|
||||
06774+I_IOA+AMB_TD, 06775+I_IOA+AMB_TD, 06776+I_IOA+AMB_TD, 06777+I_IOA+AMB_TD,
|
||||
06530+I_NPN, 06531+I_NPN, 06532+I_NPN, 06533+I_NPN, /* AD */
|
||||
06534+I_NPN, 06535+I_NPN, 06536+I_NPN, 06537+I_NPN,
|
||||
06601+I_NPN, 06603+I_NPN, 06605+I_NPN,
|
||||
06601+I_NPN, 06603+I_NPN, 06605+I_NPN, /* DF/RF */
|
||||
06611+I_NPN, 06612+I_NPN, 06615+I_NPN, 06616+I_NPN,
|
||||
06611+I_NPN, 06615+I_NPN, 06616+I_NPN,
|
||||
06621+I_NPN, 06622+I_NPN, 06623+I_NPN, 06626+I_NPN,
|
||||
06641+I_NPN, 06643+I_NPN, 06645+I_NPN,
|
||||
06661+I_NPN, 06662+I_NPN, 06663+I_NPN,
|
||||
06661+I_NPN, 06662+I_NPN, 06663+I_NPN, /* LPT */
|
||||
06664+I_NPN, 06665+I_NPN, 06666+I_NPN, 06667+I_NPN,
|
||||
06701+I_NPN, 06702+I_NPN, 06703+I_NPN,
|
||||
06701+I_NPN, 06702+I_NPN, 06703+I_NPN, /* MT */
|
||||
06704+I_NPN, 06705+I_NPN, 06706+I_NPN, 06707+I_NPN,
|
||||
06711+I_NPN, 06712+I_NPN, 06713+I_NPN,
|
||||
06714+I_NPN, 06715+I_NPN, 06716+I_NPN, 06717+I_NPN,
|
||||
06721+I_NPN, 06722+I_NPN, 06723+I_NPN, 06724+I_NPN, 06725+I_NPN,
|
||||
06741+I_NPN, 06742+I_NPN, 06743+I_NPN,
|
||||
06741+I_NPN, 06742+I_NPN, 06743+I_NPN, /* RK */
|
||||
06744+I_NPN, 06745+I_NPN, 06746+I_NPN, 06747+I_NPN,
|
||||
06751+I_NPN, 06752+I_NPN, 06753+I_NPN,
|
||||
06751+I_NPN, 06752+I_NPN, 06753+I_NPN, /* RX */
|
||||
06754+I_NPN, 06755+I_NPN, 06756+I_NPN, 06757+I_NPN,
|
||||
06761+I_NPN, 06762+I_NPN, 06764+I_NPN, 06766+I_NPN,
|
||||
06761+I_NPN, 06762+I_NPN, 06764+I_NPN, 06766+I_NPN, /* DT */
|
||||
06771+I_NPN, 06772+I_NPN, 06774+I_NPN,
|
||||
06600+I_NPN, 06601+I_NPN, 06602+I_NPN, 06603+I_NPN,
|
||||
06604+I_NPN, 06605+I_NPN, 06607+I_NPN,
|
||||
06610+I_NPN, 06611+I_NPN, 06612+I_NPN, 06613+I_NPN,
|
||||
06614+I_NPN, 06615+I_NPN, 06617+I_NPN,
|
||||
06360+I_NPN, 06361+I_NPN, 06362+I_NPN, 06363+I_NPN,
|
||||
06360+I_NPN, 06361+I_NPN, 06362+I_NPN, 06363+I_NPN, /* TSC */
|
||||
06364+I_NPN, 06365+I_NPN, 06366+I_NPN, 06367+I_NPN,
|
||||
|
||||
06201+I_FLD, 06202+I_FLD, 06203+I_FLD,
|
||||
@@ -395,7 +425,7 @@ return sp;
|
||||
t_stat fprint_sym (FILE *of, t_addr addr, t_value *val,
|
||||
UNIT *uptr, int32 sw)
|
||||
{
|
||||
int32 cflag, i, j, sp, inst, disp;
|
||||
int32 cflag, i, j, sp, inst, disp, opc;
|
||||
extern int32 emode;
|
||||
|
||||
cflag = (uptr == NULL) || (uptr == &cpu_unit);
|
||||
@@ -419,14 +449,32 @@ if (!(sw & SWMASK ('M'))) return SCPE_ARG;
|
||||
|
||||
/* Instruction decode */
|
||||
|
||||
inst = val[0] | ((emode & 1) << 12); /* include EAE mode */
|
||||
opc = (inst >> 9) & 07; /* get major opcode */
|
||||
if (opc == 07) /* operate? */
|
||||
inst = inst | ((emode & 1) << 12); /* include EAE mode */
|
||||
if (opc == 06) { /* IOT? */
|
||||
DEVICE *dptr;
|
||||
DIB *dibp;
|
||||
uint32 dno = (inst >> 3) & 077;
|
||||
for (i = 0; (dptr = amb_dev[i]) != NULL; i++) { /* check amb devices */
|
||||
if ((dptr->ctxt == NULL) || /* no DIB or */
|
||||
(dptr->flags & DEV_DIS)) continue; /* disabled? skip */
|
||||
dibp = (DIB *) dptr->ctxt; /* get DIB */
|
||||
if ((dno >= dibp->dev) || /* IOT for this dev? */
|
||||
(dno < (dibp->dev + dibp->num))) {
|
||||
inst = inst | ((i + 1) << 12); /* disambiguate */
|
||||
break; /* done */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; opc_val[i] >= 0; i++) { /* loop thru ops */
|
||||
j = (opc_val[i] >> I_V_FL) & I_M_FL; /* get class */
|
||||
if ((opc_val[i] & 017777) == (inst & masks[j])) { /* match? */
|
||||
if ((opc_val[i] & 077777) == (inst & masks[j])) { /* match? */
|
||||
|
||||
switch (j) { /* case on class */
|
||||
|
||||
case I_V_NPN: /* no operands */
|
||||
case I_V_NPN: case I_V_IOA: /* no operands */
|
||||
fprintf (of, "%s", opcode[i]); /* opcode */
|
||||
break;
|
||||
|
||||
@@ -454,7 +502,7 @@ for (i = 0; opc_val[i] >= 0; i++) { /* loop thru ops */
|
||||
break;
|
||||
|
||||
case I_V_OP2: /* operate group 2 */
|
||||
if (opcode[i]) fprintf (of, "%s", opcode[i]); /* skips */
|
||||
if (opcode[i]) fprintf (of, "%s", opcode[i]); /* skips */
|
||||
fprint_opr (of, inst & 0206, j, opcode[i] != NULL);
|
||||
break;
|
||||
|
||||
@@ -566,7 +614,8 @@ switch (j) { /* case on class */
|
||||
}
|
||||
break;
|
||||
|
||||
case I_V_NPN: case I_V_OP1: case I_V_OP2: case I_V_OP3: /* operates */
|
||||
case I_V_OP1: case I_V_OP2: case I_V_OP3: /* operates */
|
||||
case I_V_NPN: case I_V_IOA:
|
||||
for (cptr = get_glyph (cptr, gbuf, 0); gbuf[0] != 0;
|
||||
cptr = get_glyph (cptr, gbuf, 0)) {
|
||||
for (i = 0; (opcode[i] != NULL) &&
|
||||
|
||||
@@ -681,7 +681,7 @@ return SCPE_OK;
|
||||
|
||||
/* Bootstrap routine - OS/8 only
|
||||
|
||||
1) Read reverse until reverse end zone (mark track is complement obverse
|
||||
1) Read reverse until reverse end zone (mark track is complement obverse)
|
||||
2) Read forward until mark track code 031. This is a composite code from
|
||||
the last 4b of the forward block number and the first two bits of the
|
||||
reverse guard (01 -0110 01- 1010). There are 16 lines before the first
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* pdp8_tt.c: PDP-8 console terminal simulator
|
||||
|
||||
Copyright (c) 1993-2005, Robert M Supnik
|
||||
Copyright (c) 1993-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,8 @@
|
||||
|
||||
tti,tto KL8E terminal input/output
|
||||
|
||||
18-Oct-06 RMS Synced keyboard to clock
|
||||
30-Sep-06 RMS Fixed handling of non-printable characters in KSR mode
|
||||
22-Nov-05 RMS Revised for new terminal processing routines
|
||||
28-May-04 RMS Removed SET TTI CTRL-C
|
||||
29-Dec-03 RMS Added console output backpressure support
|
||||
@@ -41,6 +43,7 @@
|
||||
#include <ctype.h>
|
||||
|
||||
extern int32 int_req, int_enable, dev_done, stop_inst;
|
||||
extern int32 tmxr_poll;
|
||||
|
||||
int32 tti (int32 IR, int32 AC);
|
||||
int32 tto (int32 IR, int32 AC);
|
||||
@@ -60,7 +63,7 @@ t_stat tty_set_mode (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||
|
||||
DIB tti_dib = { DEV_TTI, 1, { &tti } };
|
||||
|
||||
UNIT tti_unit = { UDATA (&tti_svc, TT_MODE_KSR, 0), KBD_POLL_WAIT };
|
||||
UNIT tti_unit = { UDATA (&tti_svc, TT_MODE_KSR, 0), 0 };
|
||||
|
||||
REG tti_reg[] = {
|
||||
{ ORDATA (BUF, tti_unit.buf, 8) },
|
||||
@@ -68,7 +71,7 @@ REG tti_reg[] = {
|
||||
{ FLDATA (ENABLE, int_enable, INT_V_TTI) },
|
||||
{ FLDATA (INT, int_req, INT_V_TTI) },
|
||||
{ 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 }
|
||||
};
|
||||
|
||||
@@ -170,7 +173,7 @@ t_stat tti_svc (UNIT *uptr)
|
||||
{
|
||||
int32 c;
|
||||
|
||||
sim_activate (uptr, uptr->wait); /* continue poll */
|
||||
sim_activate (uptr, KBD_WAIT (uptr->wait, tmxr_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) | TTUF_KSR);
|
||||
@@ -188,7 +191,7 @@ tti_unit.buf = 0;
|
||||
dev_done = dev_done & ~INT_TTI; /* clear done, int */
|
||||
int_req = int_req & ~INT_TTI;
|
||||
int_enable = int_enable | INT_TTI; /* set enable */
|
||||
sim_activate (&tti_unit, tti_unit.wait); /* activate unit */
|
||||
sim_activate_abs (&tti_unit, KBD_WAIT (tti_unit.wait, tmxr_poll));
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
@@ -234,7 +237,7 @@ t_stat tto_svc (UNIT *uptr)
|
||||
int32 c;
|
||||
t_stat r;
|
||||
|
||||
c = sim_tt_outcvt (uptr->buf, TT_GET_MODE (uptr->flags));
|
||||
c = sim_tt_outcvt (uptr->buf, TT_GET_MODE (uptr->flags) | TTUF_KSR);
|
||||
if (c >= 0) {
|
||||
if ((r = sim_putchar_s (c)) != SCPE_OK) { /* output char; error? */
|
||||
sim_activate (uptr, uptr->wait); /* try again */
|
||||
|
||||
@@ -283,7 +283,7 @@ switch (pulse) { /* case IR<9:11> */
|
||||
case 1: /* TSF */
|
||||
return (dev_done & itto)? IOT_SKP + AC: AC;
|
||||
|
||||
case 2: /* TCF */
|
||||
case 2: /* TCF */
|
||||
dev_done = dev_done & ~itto; /* clear flag */
|
||||
int_req = int_req & ~itto; /* clear intr */
|
||||
break;
|
||||
@@ -295,7 +295,7 @@ switch (pulse) { /* case IR<9:11> */
|
||||
dev_done = dev_done & ~itto; /* clear flag */
|
||||
int_req = int_req & ~itto; /* clear int req */
|
||||
case 4: /* TPC */
|
||||
sim_activate (&ttox_unit[ln], ttox_unit[ln].wait); /* activate */
|
||||
sim_activate (&ttox_unit[ln], ttox_unit[ln].wait); /* activate */
|
||||
ttox_buf[ln] = AC & 0377; /* load buffer */
|
||||
break;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user