I1620: Update various CPU issues

- Changed to commit PC on certain stops
- Added SET CPU RELEASE command
- Undefined indicators don't throw an error (Dave Wise)
- Added Model I mode to allow record marks in adds (Dave Wise)
- Allowed undocumented indicator 8 (Dave Wise)
- Added option for Model I diagnostic mode (Dave Wise)

# Conflicts:
#	I1620/i1620_cpu.c
This commit is contained in:
Mark Pizzolato 2017-05-21 21:47:30 -07:00
parent d72ab3ce51
commit c4c8043215
2 changed files with 74 additions and 17 deletions

View file

@ -26,6 +26,11 @@
This CPU module incorporates code and comments from the 1620 simulator by
Geoff Kuenning, with his permission.
20-May-17 RMS Changed to commit PC on certain stops
Added SET CPU RELEASE command
Undefined indicators don't throw an error (Dave Wise)
19-May-17 RMS Added Model I mode to allow record marks in adds (Dave Wise)
18-May-17 RMS Allowed undocumented indicator 8 (Dave Wise)
13-Mar-17 RMS Added error test on device addr (COVERITY)
07-May-15 RMS Added missing TFL instruction (Tom McBride)
28-Mar-15 RMS Revised to use sim_printf
@ -120,6 +125,7 @@ typedef struct {
uint8 M[MAXMEMSIZE] = { 0 }; /* main memory */
uint32 saved_PC = 0; /* saved PC */
uint32 actual_PC = 0; /* actual PC at halt */
uint32 IR2 = 1; /* inst reg 2 */
uint32 PAR = 0; /* P address */
uint32 QAR = 0; /* Q address */
@ -147,6 +153,7 @@ t_stat cpu_set_model (UNIT *uptr, int32 val, CONST char *cptr, void *desc);
t_stat cpu_set_size (UNIT *uptr, int32 val, CONST char *cptr, void *desc);
t_stat cpu_set_save (UNIT *uptr, int32 val, CONST char *cptr, void *desc);
t_stat cpu_set_table (UNIT *uptr, int32 val, CONST char *cptr, void *desc);
t_stat cpu_set_release (UNIT *uptr, int32 val, CONST char *cptr, void *desc);
t_stat cpu_set_hist (UNIT *uptr, int32 val, CONST char *cptr, void *desc);
t_stat cpu_show_hist (FILE *st, UNIT *uptr, int32 val, CONST void *desc);
@ -203,6 +210,7 @@ UNIT cpu_unit = { UDATA (NULL, UNIT_FIX+UNIT_BCD+MI_STD, MAXMEMSIZE) };
REG cpu_reg[] = {
{ DRDATA (PC, saved_PC, 16), PV_LEFT },
{ DRDATA (APC, actual_PC, 16), PV_LEFT + REG_HRO },
{ DRDATA (IR2, IR2, 16), PV_LEFT },
{ DRDATA (PR1, PR1, 16), PV_LEFT },
{ DRDATA (PAR, PAR, 16), PV_LEFT + REG_RO },
@ -237,6 +245,8 @@ MTAB cpu_mod[] = {
{ IF_EDT, 0, "no EDT", "NOEDT", &cpu_set_opt1 },
{ IF_DIV, IF_DIV, "DIV", "DIV", &cpu_set_opt1 },
{ IF_DIV, 0, "no DIV", "NODIV", &cpu_set_opt1 },
{ IF_RMOK, IF_RMOK, "RM allowed", "RMOK", &cpu_set_opt1 },
{ IF_RMOK, 0, "RM disallowed", "NORMOK", &cpu_set_opt1 },
{ IF_FP, IF_FP, "FP", "FP", NULL },
{ IF_FP, 0, "no FP", "NOFP", NULL },
{ IF_BIN, IF_BIN, "BIN", "BIN", &cpu_set_opt2 },
@ -252,6 +262,8 @@ MTAB cpu_mod[] = {
{ UNIT_MSIZE, 0, NULL, "TABLE", &cpu_set_table },
{ MTAB_XTD|MTAB_VDV|MTAB_NMO|MTAB_SHP, 0, "HISTORY", "HISTORY",
&cpu_set_hist, &cpu_show_hist },
{ MTAB_XTD|MTAB_VDV|MTAB_NMO, 0, NULL, "RELEASE",
&cpu_set_release, NULL },
{ 0 }
};
@ -407,10 +419,12 @@ const uint8 k_valid_p[NUM_IO] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
/* Indicator table: -1 = illegal, +1 = resets when tested */
/* Indicator table: -1 = undefined, +1 = resets when tested */
/* Indicator 8 is MAR CHECK, for maintenance use only */
/* Undefined indicators always read as 0 */
const int32 ind_table[NUM_IND] = {
-1, 0, 0, 0, 0, -1, 1, 1, -1, 1, /* 00 - 09 */
-1, 0, 0, 0, 0, -1, 1, 1, 0, 1, /* 00 - 09 */
-1, 0, 0, 0, 1, 1, 1, 1, -1, 0, /* 10 - 19 */
-1, -1, -1, -1, -1, 0, -1, -1, -1, -1, /* 20 - 29 */
0, 0, 0, 1, 1, 0, 1, 1, 1, 0, /* 30 - 39 */
@ -469,6 +483,12 @@ const uint8 std_mul_table[MUL_TABLE_LEN] = {
5, 4, 4, 5, 3, 6, 2, 7, 1, 8
};
/* Table of stop codes that commit PC before returning to SCP */
static t_stat commit_pc[] = {
STOP_HALT, SCPE_STOP, STOP_NOCD, SCPE_EOF, SCPE_IOERR, 0
};
#define BRANCH(x) PCQ_ENTRY; PC = (x)
#define GET_IDXADDR(x) ((idxb? IDX_B: IDX_A) + ((x) * ADDR_LEN) + (ADDR_LEN - 1))
@ -486,11 +506,11 @@ if ((cpu_unit.flags & IF_IA) == 0)
if ((cpu_unit.flags & IF_IDX) == 0)
idxe = idxb = 0;
upd_ind (); /* update indicators */
reason = 0;
reason = SCPE_OK;
/* Main instruction fetch/decode loop */
while (reason == 0) { /* loop until halted */
while (reason == SCPE_OK) { /* loop until halted */
saved_PC = PC; /* commit prev instr */
if (sim_interval <= 0) { /* check clock queue */
@ -554,7 +574,7 @@ while (reason == 0) { /* loop until halted */
hst[hst_p].inst[i] = M[(PC + i) % MEMSIZE];
}
PC = PC + INST_LEN; /* advance PC */
PC = ADDR_A (PC, INST_LEN); /* advance PC */
switch (op) { /* case on op */
/* Transmit digit - P,Q are valid */
@ -685,7 +705,7 @@ while (reason == 0) { /* loop until halted */
case OP_BNI:
upd_ind (); /* update indicators */
t = get_2d (ADDR_A (saved_PC, I_BR)); /* get ind number */
if ((t < 0) || (ind_table[t] < 0)) { /* not valid? */
if (t < 0) { /* not valid? */
reason = STOP_INVIND; /* stop */
break;
}
@ -1037,7 +1057,6 @@ while (reason == 0) { /* loop until halted */
/* Halt */
case OP_H:
saved_PC = PC; /* commit inst */
reason = STOP_HALT; /* stop */
break;
@ -1056,6 +1075,11 @@ while (reason == 0) { /* loop until halted */
/* Simulation halted */
for (i = 0; commit_pc[i] != 0; i++) { /* check stop code */
if (reason == commit_pc[i]) /* on list? */
saved_PC = PC; /* commit PC */
}
actual_PC = PC; /* save cur PC for RLS */
pcq_r->qptr = pcq_p; /* update pc q ptr */
upd_ind ();
return reason;
@ -1342,6 +1366,9 @@ return SCPE_OK;
Reference Manual: "When the sum is zero, the sign of the P field
is retained."
Model 1 hack: If the Q field contains a record mark, it is treated
as 0 (Dave Wise; from schematics).
*/
t_stat add_field (uint32 d, uint32 s, t_bool sub, uint32 skp, int32 *sta)
@ -1358,6 +1385,9 @@ ind[IN_EZ] = 1; /* assume zero */
dst = M[d] & DIGIT; /* 1st digits */
src = M[s] & DIGIT;
if ((src == REC_MARK) && /* Q record mark? */
((cpu_unit.flags & IF_RMOK) != 0)) /* Model I & enabled? */
src = 0; /* treat as 0 */
if (BAD_DIGIT (dst) || BAD_DIGIT (src)) /* bad digit? */
return STOP_INVDIG;
if (comp) /* complement? */
@ -1375,6 +1405,9 @@ do {
if (cnt >= skp) /* get src flag */
src_f = M[s] & FLAG;
MM (s); /* decr src addr */
if ((src == REC_MARK) && /* Q record mark? */
((cpu_unit.flags & IF_RMOK) != 0)) /* Model I & enabled? */
src = 0; /* treat as 0 */
}
if (BAD_DIGIT (dst) || BAD_DIGIT (src)) /* bad digit? */
return STOP_INVDIG;
@ -1423,6 +1456,8 @@ return SCPE_OK;
In the unlike signs case, the compare is abandoned as soon as a non-zero
digit is seen; zeroes go through the normal flows.
See add for Model I hack in handling Q field record marks.
*/
t_stat cmp_field (uint32 d, uint32 s)
@ -1448,12 +1483,15 @@ do {
src_f = M[s] & FLAG; /* get src flag */
MM (s); /* decr src addr */
}
if (BAD_DIGIT (dst) || BAD_DIGIT (src)) /* bad digit? */
return STOP_INVDIG;
if (unlike && ((dst | src) != 0)) { /* unlike signs, digit? */
ind[IN_EZ] = 0; /* not equal */
return SCPE_OK;
}
if ((src == REC_MARK) && /* Q record mark? */
((cpu_unit.flags & IF_RMOK) != 0)) /* Model I & enabled? */
src = 0; /* treat as 0 */
if (BAD_DIGIT (dst) || BAD_DIGIT (src)) /* bad digit? */
return STOP_INVDIG;
src = (d != dsv)? 9 - src: 10 - src; /* complement */
add_one_digit (dst, src, &cry); /* throw away result */
MM (d); /* decr dst addr */
@ -2114,12 +2152,26 @@ if (pcq_r)
else return SCPE_IERR;
sim_brk_types = sim_brk_dflt = SWMASK ('E'); /* init breakpoints */
upd_ind (); /* update indicators */
if (one_time) /* set default tables */
if (one_time) { /* set default tables */
cpu_set_table (&cpu_unit, 1, NULL, NULL);
actual_PC = saved_PC = 0; /* sync PCs */
}
one_time = FALSE;
return SCPE_OK;
}
/* Release routine */
t_stat cpu_set_release (UNIT *uptr, int32 val, CONST char *cptr, void *desc)
{
if (actual_PC == ADDR_A (saved_PC, INST_LEN)) { /* one instr ahead? */
saved_PC = actual_PC; /* return */
sim_printf ("New PC = %05d\n", saved_PC);
}
else sim_printf ("PC unchanged\n");
return SCPE_OK;
}
/* Memory examine */
t_stat cpu_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw)
@ -2176,7 +2228,9 @@ return SCPE_OK;
t_stat cpu_set_opt1 (UNIT *uptr, int32 val, CONST char *cptr, void *desc)
{
if (cpu_unit.flags & IF_MII) {
sim_printf ("Feature is standard on 1620 Model 2\n");
if ((val & IF_RMOK) != 0)
sim_printf ("Feature is not available on 1620 Model 2\n");
else sim_printf ("Feature is standard on 1620 Model 2\n");
return SCPE_NOFNC;
}
return SCPE_OK;

View file

@ -1,6 +1,6 @@
/* i1620_defs.h: IBM 1620 simulator definitions
Copyright (c) 2002-2015, Robert M. Supnik
Copyright (c) 2002-2017, Robert M. Supnik
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
@ -27,6 +27,7 @@
I am grateful to Al Kossow, the Computer History Museum, and the IBM Corporate
Archives for their help in gathering documentation about the IBM 1620.
19-May-17 RMS Added option for Model I diagnostic mode (Dave Wise)
05-Feb-15 TFM Added definitions for flagged RM, GM, NB
22-May-10 RMS Added check for 64b definitions
18-Oct-02 RMS Fixed bug in ADDR_S macro (found by Hans Pufal)
@ -120,6 +121,7 @@
#define IN_EXPCHK 15 /* floating exponent check */
#define IN_MBREVEN 16 /* even parity check */
#define IN_MBRODD 17 /* odd parity check */
#define IN_MARCHK 18 /* MAR check - diag only */
#define IN_ANYCHK 19 /* any of read, write, even/odd */
#define IN_PRCHK 25 /* printer check */
#define IN_IXN 30 /* IX neither */
@ -197,12 +199,13 @@
#define IF_4QA (1 << (UNIT_V_UF + 9)) /* 4 char Q addr */
#define IF_NQX (1 << (UNIT_V_UF + 10)) /* no Q indexing */
#define IF_IMM (1 << (UNIT_V_UF + 11)) /* immediate */
#define UNIT_BCD (1 << (UNIT_V_UF + 12)) /* BCD coded */
#define UNIT_MSIZE (1 << (UNIT_V_UF + 13)) /* fake flag */
#define ALLOPT (IF_DIV + IF_IA + IF_EDT + IF_FP + IF_BIN + IF_IDX)
#define MI_OPT (IF_DIV + IF_IA + IF_EDT + IF_FP)
#define IF_RMOK (1 << (UNIT_V_UF + 12)) /* diag mode - force rm to 0 */
#define UNIT_BCD (1 << (UNIT_V_UF + 13)) /* BCD coded */
#define UNIT_MSIZE (1 << (UNIT_V_UF + 14)) /* fake flag */
#define ALLOPT (IF_DIV + IF_IA + IF_EDT + IF_FP + IF_BIN + IF_IDX + IF_RMOK)
#define MI_OPT (IF_DIV + IF_IA + IF_EDT + IF_FP + IF_RMOK)
#define MI_STD (IF_DIV + IF_IA + IF_EDT)
#define MII_OPT (ALLOPT)
#define MII_OPT (IF_DIV + IF_IA + IF_EDT + IF_FP + IF_BIN + IF_IDX)
#define MII_STD (IF_DIV + IF_IA + IF_EDT + IF_BIN + IF_IDX)
/* Add status codes */