B5500: Second release of Burroughs B5500 simulator.

1) Minor cleanup of some instruction execution to better match
     flowcharts.
  2) Changes to allow proper reboot if OS crashed.
  3) Changes to terminal muliplexer to allow for simH expect/send
     to work.
  4) Some corrections to translation table.
  5) Support for new sim_card interface. This includes support for
     stacking of multiple decks on the input stream.
This commit is contained in:
Richard Cornwell 2018-08-05 22:43:59 -04:00
parent 8b1d058a63
commit b4d185f3af
8 changed files with 188 additions and 150 deletions

View file

@ -213,7 +213,7 @@ uint16 l_reg[2]; /* L current syllable pointer */
uint8 ncsf_reg[2]; /* True if normal state */ uint8 ncsf_reg[2]; /* True if normal state */
uint8 salf_reg[2]; /* True if subrogram mode */ uint8 salf_reg[2]; /* True if subrogram mode */
uint8 cwmf_reg[2]; /* True if character mode */ uint8 cwmf_reg[2]; /* True if character mode */
uint8 hltf[2]; /* True if processor halted */ uint16 hltf[2]; /* True if processor halted */
uint8 msff_reg[2]; /* Mark stack flag Word mode */ uint8 msff_reg[2]; /* Mark stack flag Word mode */
#define TFFF MSFF /* True state in Char mode */ #define TFFF MSFF /* True state in Char mode */
uint8 varf_reg[2]; /* Variant Flag */ uint8 varf_reg[2]; /* Variant Flag */
@ -926,7 +926,7 @@ void initiate() {
/* Save processor state in case of error or halt */ /* Save processor state in case of error or halt */
void storeInterrupt(int forced, int test) { void storeInterrupt(int forced, int test) {
int f; int f;
t_uint64 temp; uint16 temp;
if (forced || test) if (forced || test)
NCSF = 0; NCSF = 0;
@ -1985,7 +1985,7 @@ sim_instr(void)
int i; int i;
int j; int j;
reason = 0; reason = SCPE_OK;
hltf[0] = 0; hltf[0] = 0;
hltf[1] = 0; hltf[1] = 0;
P1_run = 1; P1_run = 1;
@ -1993,19 +1993,18 @@ sim_instr(void)
while (reason == 0) { /* loop until halted */ while (reason == 0) { /* loop until halted */
if (P1_run == 0) if (P1_run == 0)
return SCPE_STOP; return SCPE_STOP;
/* System is booting, wait until finished loading */
while (loading) { while (loading) {
sim_interval = -1;
reason = sim_process_event(); reason = sim_process_event();
if (reason != SCPE_OK) { if (reason != SCPE_OK)
break; /* process */ break; /* process */
} }
} /* Passed time quantum */
if (sim_interval <= 0) { /* event queue? */ if (sim_interval <= 0) { /* event queue? */
reason = sim_process_event(); reason = sim_process_event();
if (reason != SCPE_OK) { if (reason != SCPE_OK)
break; /* process */ break; /* process */
} }
}
if (sim_brk_summ) { if (sim_brk_summ) {
if(sim_brk_test((C << 3) | L, SWMASK('E'))) { if(sim_brk_test((C << 3) | L, SWMASK('E'))) {
@ -2027,20 +2026,15 @@ sim_instr(void)
} }
/* Toggle between two CPU's. */ /* Toggle between two CPU's. */
if (TROF == 0 && NCSF) {
if (Q != 0 || ((cpu_index)? HLTF : IAR) != 0)
storeInterrupt(1,0);
}
if (cpu_index == 0 && P2_run == 1) { if (cpu_index == 0 && P2_run == 1) {
cpu_index = 1; cpu_index = 1;
/* Check if interrupt pending. */
if (TROF == 0 && NCSF && ((Q != 0) || HLTF))
/* Force a SFI */
storeInterrupt(1,0);
} else { } else {
cpu_index = 0; cpu_index = 0;
/* Check if interrupt pending. */
if (TROF == 0 && NCSF && ((Q != 0) ||
(IAR != 0)))
/* Force a SFI */
storeInterrupt(1,0);
} }
if (TROF == 0) if (TROF == 0)
next_prog(); next_prog();
@ -2184,17 +2178,12 @@ crf_loop:
Ma = (F - field) & CORE; Ma = (F - field) & CORE;
memory_cycle(4); memory_cycle(4);
AROF = 0; AROF = 0;
if (A & FLAG) {
if ((A & PRESENT) == 0) {
if (NCSF)
Q |= PRES_BIT;
break;
}
GH = 0;
} else {
GH = (A >> 12) & 070;
}
Ma = CF(A); Ma = CF(A);
GH = 0;
if ((A & FLAG) == 0)
GH = (A >> 12) & 070;
else if ((A & PRESENT) == 0 && NCSF)
Q |= PRES_BIT;
break; break;
case CMOP_RDA: /* Recall Destination Address */ case CMOP_RDA: /* Recall Destination Address */
@ -2203,17 +2192,12 @@ crf_loop:
S = (F - field) & CORE; S = (F - field) & CORE;
memory_cycle(3); memory_cycle(3);
BROF = 0; BROF = 0;
if (B & FLAG) {
if ((B & PRESENT) == 0) {
if (NCSF)
Q |= PRES_BIT;
break;
}
KV = 0;
} else {
KV = (B >> 12) & 070;
}
S = CF(B); S = CF(B);
KV = 0;
if ((B & FLAG) == 0)
KV = (B >> 12) & 070;
else if ((B & PRESENT) == 0 && NCSF)
Q |= PRES_BIT;
break; break;
case CMOP_RCA: /* Recall Control Address */ case CMOP_RCA: /* Recall Control Address */
@ -2227,10 +2211,10 @@ crf_loop:
if ((B & PRESENT) == 0) { if ((B & PRESENT) == 0) {
if (NCSF) if (NCSF)
Q |= PRES_BIT; Q |= PRES_BIT;
break; } else {
}
C = CF(B); C = CF(B);
L = 0; L = 0;
}
} else { } else {
C = CF(B); C = CF(B);
L = LF(B) + 1; L = LF(B) + 1;
@ -2318,9 +2302,10 @@ crf_loop:
A = B; A = B;
AROF = BROF; AROF = BROF;
B = ((t_uint64)(KV & 070) << (FFIELD_V - 3)) | toC(S); B = ((t_uint64)(KV & 070) << (FFIELD_V - 3)) | toC(S);
atemp = S;
S = (F - field) & CORE; S = (F - field) & CORE;
memory_cycle(013); /* Store B in S */ memory_cycle(013); /* Store B in S */
S = CF(B); S = atemp;
B = A; B = A;
BROF = AROF; BROF = AROF;
AROF = 0; AROF = 0;
@ -2331,9 +2316,10 @@ crf_loop:
A = B; A = B;
AROF = BROF; AROF = BROF;
B = ((t_uint64)(GH & 070) << (FFIELD_V - 3)) | toC(Ma); B = ((t_uint64)(GH & 070) << (FFIELD_V - 3)) | toC(Ma);
atemp = Ma;
Ma = (F - field) & CORE; Ma = (F - field) & CORE;
memory_cycle(015); /* Store B in Ma */ memory_cycle(015); /* Store B in Ma */
Ma = CF(B); Ma = atemp;
B = A; B = A;
BROF = AROF; BROF = AROF;
AROF = 0; AROF = 0;
@ -3652,6 +3638,12 @@ control:
do { do {
Ma = CF(B); Ma = CF(B);
memory_cycle(5); memory_cycle(5);
if (sim_interval <= 0) { /* event queue? */
reason = sim_process_event();
if (reason != SCPE_OK) {
break; /* process */
}
}
temp = (B & MANT) + (A & MANT); temp = (B & MANT) + (A & MANT);
} while ((temp & EXPO) == 0); } while ((temp & EXPO) == 0);
A = FLAG | PRESENT | toC(Ma); A = FLAG | PRESENT | toC(Ma);
@ -3672,17 +3664,12 @@ control:
R = 0; R = 0;
F = S; /* Set F and X */ F = S; /* Set F and X */
X = toF(S); X = toF(S);
if (B & FLAG) {
if ((B & PRESENT) == 0) {
if (NCSF)
Q |= PRES_BIT;
break;
}
KV = 0;
} else {
KV = (uint8)((B >> (FFIELD_V - 3)) & 070);
}
S = CF(B); S = CF(B);
KV = 0;
if ((B & FLAG) == 0)
KV = (uint8)((B >> (FFIELD_V - 3)) & 070);
else if ((B & PRESENT) == 0 && NCSF)
Q |= PRES_BIT;
break; break;
case VARIANT(WMOP_MKS): /* Mark Stack */ case VARIANT(WMOP_MKS): /* Mark Stack */
@ -3846,6 +3833,8 @@ cpu_reset(DEVICE * dptr)
GH = KV = Q = 0; GH = KV = Q = 0;
hltf[0] = 0; hltf[0] = 0;
P1_run = 0; P1_run = 0;
IAR = 0;
HALT = 0;
idle_addr = 0; idle_addr = 0;
sim_brk_types = sim_brk_dflt = SWMASK('E') | SWMASK('A') | SWMASK('B'); sim_brk_types = sim_brk_dflt = SWMASK('E') | SWMASK('A') | SWMASK('B');
@ -3958,7 +3947,7 @@ cpu_show_hist(FILE * st, UNIT * uptr, int32 val, CONST void *desc)
t_stat r; t_stat r;
t_value sim_eval; t_value sim_eval;
struct InstHistory *h; struct InstHistory *h;
static const char flags[] = "ABCNSMV"; CONST static char flags[] = "ABCNSMV";
if (hst_lnt == 0) if (hst_lnt == 0)
return SCPE_NOFNC; /* enabled? */ return SCPE_NOFNC; /* enabled? */
@ -4008,8 +3997,7 @@ cpu_show_hist(FILE * st, UNIT * uptr, int32 val, CONST void *desc)
fputc(' ', st); fputc(' ', st);
fprint_val(st, h->op, 8, 12, PV_RZRO); fprint_val(st, h->op, 8, 12, PV_RZRO);
fputc(' ', st); fputc(' ', st);
print_opcode(st, h->op, print_opcode(st, h->op, ((h->flags & F_CWMF) != 0));
((h->flags & F_CWMF) ? char_ops : word_ops));
fputc(' ', st); fputc(' ', st);
fprint_val(st, h->iar, 8, 16, PV_RZRO); fprint_val(st, h->iar, 8, 16, PV_RZRO);
fputc('\n', st); /* end line */ fputc('\n', st); /* end line */

View file

@ -72,8 +72,7 @@ typedef struct _opcode
} }
t_opcode; t_opcode;
extern void print_opcode(FILE * ofile, t_value val, t_opcode *); void print_opcode(FILE * ofile, t_value val, int chr_mode);
extern t_opcode word_ops[], char_ops[];
t_stat chan_reset(DEVICE *); t_stat chan_reset(DEVICE *);
t_stat chan_boot(t_uint64); t_stat chan_boot(t_uint64);

View file

@ -280,7 +280,7 @@ t_stat dsk_srv(UNIT * uptr)
chan_set_end(chan); chan_set_end(chan);
} else } else
uptr->u5 &= ~(DK_RDCK|DK_RD|DK_WR); uptr->u5 &= ~(DK_RDCK|DK_RD|DK_WR);
sim_activate(eptr, 500); sim_activate(eptr, 8000);
return SCPE_OK; return SCPE_OK;
} }
sim_activate(uptr, 100); sim_activate(uptr, 100);
@ -432,7 +432,7 @@ t_stat esu_srv(UNIT * uptr)
uptr->u5 -= DK_SECT; uptr->u5 -= DK_SECT;
} }
} }
sim_activate(uptr, (uptr->flags & MODIB) ? 200 :100); sim_activate(uptr, (uptr->flags & MODIB) ? 500 :300);
return SCPE_OK; return SCPE_OK;
} }
@ -456,8 +456,14 @@ dsk_boot(int32 unit_num, DEVICE * dptr)
t_uint64 desc; t_uint64 desc;
int i; int i;
for(i = 0; i < 20; i++) for(i = 0; i < 20; i++) {
esu_unit[i].u5 = 0; esu_unit[i].u5 = 0;
sim_cancel(&esu_unit[i]);
}
dsk_unit[0].u5 = 0;
dsk_unit[1].u5 = 0;
sim_cancel(&dsk_unit[0]);
sim_cancel(&dsk_unit[1]);
desc = (((t_uint64)dev)<<DEV_V)|DEV_IORD|DEV_OPT|020LL; desc = (((t_uint64)dev)<<DEV_V)|DEV_IORD|DEV_OPT|020LL;
return chan_boot(desc); return chan_boot(desc);

View file

@ -76,6 +76,7 @@
#define BufAbnormal 010 /* Abnornmal flag */ #define BufAbnormal 010 /* Abnornmal flag */
#define BufGM 020 /* Buffer term with GM */ #define BufGM 020 /* Buffer term with GM */
#define BufIRQ 040 /* Buffer ready */ #define BufIRQ 040 /* Buffer ready */
#define BufDisco 0100 /* Buffer disconnecting */
/* Not connected line: /* Not connected line:
BufNotReady. BufNotReady.
@ -350,7 +351,7 @@ t_stat dtc_srv(UNIT * uptr)
} }
/* Process for each unit */ /* Process for each unit */
if (uptr->u5 & DTC_WR) { if (uptr->u5 & DTC_WR) {
if (line > dtc_desc.lines || line == -1) { if (line > dtc_desc.lines || line == -1 || dtc_lstatus[line] & BufDisco) {
sim_debug(DEBUG_DETAIL, &dtc_dev, "Datacomm write invalid %d\n", sim_debug(DEBUG_DETAIL, &dtc_dev, "Datacomm write invalid %d\n",
line); line);
chan_set_notrdy(chan); chan_set_notrdy(chan);
@ -434,7 +435,7 @@ t_stat dtc_srv(UNIT * uptr)
} }
if (uptr->u5 & DTC_RD) { if (uptr->u5 & DTC_RD) {
if (line > dtc_desc.lines || line == -1) { if (line > dtc_desc.lines || line == -1 || dtc_lstatus[line] & BufDisco) {
sim_debug(DEBUG_DETAIL, &dtc_dev, "Datacomm read nothing %d\n", sim_debug(DEBUG_DETAIL, &dtc_dev, "Datacomm read nothing %d\n",
line); line);
chan_set_notrdy(chan); chan_set_notrdy(chan);
@ -489,7 +490,7 @@ t_stat dtc_srv(UNIT * uptr)
if (dtc_lstatus[line] & BufAbnormal) if (dtc_lstatus[line] & BufAbnormal)
chan_set_wcflg(chan); chan_set_wcflg(chan);
if (dtc_ldsc[line].conn == 0) /* connected? */ if (dtc_ldsc[line].conn == 0) /* connected? */
dtc_lstatus[line] = BufIRQ|BufNotReady; dtc_lstatus[line] = BufIRQ|BufAbnormal|BufIRQ|BufIdle;
else else
dtc_lstatus[line] = BufIRQ|BufIdle; dtc_lstatus[line] = BufIRQ|BufIdle;
dtc_bsize[line] = 0; dtc_bsize[line] = 0;
@ -524,6 +525,7 @@ dtco_srv(UNIT * uptr)
sim_clock_coschedule(uptr, tmxr_poll); sim_clock_coschedule(uptr, tmxr_poll);
ln = tmxr_poll_conn(&dtc_desc); /* look for connect */ ln = tmxr_poll_conn(&dtc_desc); /* look for connect */
if (ln >= 0) { /* got one? */ if (ln >= 0) { /* got one? */
dtc_ldsc[ln].rcve = 1;
dtc_blimit[ln] = dtc_bufsize-1; dtc_blimit[ln] = dtc_bufsize-1;
dtc_lstatus[ln] = BufIRQ|BufAbnormal|BufWriteRdy; dtc_lstatus[ln] = BufIRQ|BufAbnormal|BufWriteRdy;
IAR |= IRQ_12; IAR |= IRQ_12;
@ -532,32 +534,43 @@ dtco_srv(UNIT * uptr)
/* For each line that is in idle state enable recieve */ /* For each line that is in idle state enable recieve */
for (ln = 0; ln < dtc_desc.lines; ln++) { for (ln = 0; ln < dtc_desc.lines; ln++) {
dtc_ldsc[ln].rcve = 0;
if (dtc_ldsc[ln].conn && if (dtc_ldsc[ln].conn &&
(dtc_lstatus[ln] & BufSMASK) == BufIdle) { (dtc_lstatus[ln] & BufSMASK) < BufWrite) {
dtc_ldsc[ln].rcve = 1; dtc_ldsc[ln].rcve = 1;
} }
} }
tmxr_poll_rx(&dtc_desc); /* poll for input */ tmxr_poll_rx(&dtc_desc); /* poll for input */
for (ln = 0; ln < DTC_MLINES; ln++) { /* loop thru mux */ for (ln = 0; ln < DTC_MLINES; ln++) { /* loop thru mux */
/* Check for disconnect */ /* Check for disconnect */
if (dtc_ldsc[ln].conn == 0) { /* connected? */ if (dtc_ldsc[ln].conn == 0 && (dtc_lstatus[ln] & BufDisco) == 0) { /* connected? */
dtc_ldsc[ln].rcve = 0;
switch(dtc_lstatus[ln] & BufSMASK) { switch(dtc_lstatus[ln] & BufSMASK) {
case BufIdle: /* Idle, throw in EOT */ case BufIdle: /* Idle Flag as disconnected */
/* Fall through */ dtc_lstatus[ln] = BufIRQ|BufAbnormal|BufIdle|BufDisco;
dtc_bsize[ln] = 0;
IAR |= IRQ_12;
sim_debug(DEBUG_DETAIL, &dtc_dev, "Datacomm disconnect %d idle\n", ln);
break;
case BufWriteRdy: /* Awaiting output, terminate */ case BufWriteRdy: /* Awaiting output, terminate */
dtc_bufptr[ln] = 0; dtc_bufptr[ln] = 0;
/* Fall through */ /* Fall through */
case BufInputBusy: /* reading, terminate with EOT */ case BufInputBusy: /* reading, terminate with EOT */
dtc_buf[ln][dtc_bufptr[ln]++] = 017; dtc_buf[ln][dtc_bufptr[ln]++] = 017;
dtc_bsize[ln] = dtc_bufptr[ln]; dtc_bsize[ln] = dtc_bufptr[ln]+1;
dtc_lstatus[ln] = BufIRQ|BufAbnormal|BufReadRdy; dtc_lstatus[ln] = BufIRQ|BufAbnormal|BufReadRdy;
IAR |= IRQ_12; IAR |= IRQ_12;
sim_debug(DEBUG_DETAIL, &dtc_dev, "Datacomm disconnect %d write\n", ln);
break; break;
case BufOutBusy: /* Terminate Output */ case BufOutBusy: /* Terminate Output */
dtc_lstatus[ln] = BufIRQ|BufIdle; dtc_lstatus[ln] = BufIRQ|BufIdle|BufAbnormal;
dtc_bsize[ln] = 0; dtc_bsize[ln] = 0;
IAR |= IRQ_12; IAR |= IRQ_12;
sim_debug(DEBUG_DETAIL, &dtc_dev, "Datacomm disconnect %d out\n", ln);
break; break;
default: /* Other cases, ignore until default: /* Other cases, ignore until
in better state */ in better state */
break; break;
@ -568,23 +581,29 @@ dtco_srv(UNIT * uptr)
switch(dtc_lstatus[ln] & BufSMASK) { switch(dtc_lstatus[ln] & BufSMASK) {
case BufIdle: case BufIdle:
/* If we have any data to receive */ /* If we have any data to receive */
if (tmxr_rqln(&dtc_ldsc[ln]) > 0) if (tmxr_rqln(&dtc_ldsc[ln]) > 0) {
dtc_lstatus[ln] = BufInputBusy; dtc_lstatus[ln] &= ~(BufSMASK);
else dtc_lstatus[ln] |= BufInputBusy;
} else
break; /* Nothing to do */ break; /* Nothing to do */
sim_debug(DEBUG_DETAIL, &dtc_dev, "Datacomm recieve %d idle\n", sim_debug(DEBUG_DETAIL, &dtc_dev, "Datacomm recieve %d idle\n",
ln); ln);
dtc_bufptr[ln] = 0; dtc_bufptr[ln] = 0;
dtc_bsize[ln] = 0; dtc_bsize[ln] = 0;
/* Fall through */
case BufInputBusy: case BufInputBusy:
t = 1; t = 1;
while (t && tmxr_rqln(&dtc_ldsc[ln]) != 0) { while (t) {
c = tmxr_getc_ln(&dtc_ldsc[ln]) & 0x7f; /* get char */ c = tmxr_getc_ln(&dtc_ldsc[ln]); /* get char */
if (c == 0)
break;
c &= 0x7f;
c1 = ascii_to_con[c]; c1 = ascii_to_con[c];
switch(c) { switch(c) {
case '\005': /* ^E ENQ who-are-you */ case '\005': /* ^E ENQ who-are-you */
dtc_lstatus[ln] &= ~(BufSMASK); dtc_lstatus[ln] &= ~(BufSMASK);
dtc_lstatus[ln] |= BufIRQ|BufAbnormal|BufWriteRdy; dtc_lstatus[ln] |= BufIRQ|BufWriteRdy|BufAbnormal;
IAR |= IRQ_12; IAR |= IRQ_12;
sim_debug(DEBUG_DETAIL, &dtc_dev, sim_debug(DEBUG_DETAIL, &dtc_dev,
"Datacomm recieve ENQ %d\n", ln); "Datacomm recieve ENQ %d\n", ln);
@ -786,15 +805,14 @@ t_stat dtc_setnl (UNIT *uptr, int32 val, CONST char *cptr, void *desc)
newln = (int32) get_uint (cptr, 10, DTC_MLINES, &r); newln = (int32) get_uint (cptr, 10, DTC_MLINES, &r);
if ((r != SCPE_OK) || (newln == dtc_desc.lines)) if ((r != SCPE_OK) || (newln == dtc_desc.lines))
return r; return r;
if ((newln == 0) || (newln >= DTC_MLINES)) if ((newln == 0) || (newln > DTC_MLINES))
return SCPE_ARG; return SCPE_ARG;
newln--;
if (newln < dtc_desc.lines) { if (newln < dtc_desc.lines) {
for (i = newln, t = 0; i < dtc_desc.lines; i++) for (i = newln-1, t = 0; i < dtc_desc.lines; i++)
t = t | dtc_ldsc[i].conn; t = t | dtc_ldsc[i].conn;
if (t && !get_yn ("This will disconnect users; proceed [N]?", FALSE)) if (t && !get_yn ("This will disconnect users; proceed [N]?", FALSE))
return SCPE_OK; return SCPE_OK;
for (i = newln; i < dtc_desc.lines; i++) { for (i = newln-1; i < dtc_desc.lines; i++) {
if (dtc_ldsc[i].conn) { if (dtc_ldsc[i].conn) {
tmxr_linemsg (&dtc_ldsc[i], "\r\nOperator disconnected line\r\n"); tmxr_linemsg (&dtc_ldsc[i], "\r\nOperator disconnected line\r\n");
tmxr_send_buffered_data (&dtc_ldsc[i]); tmxr_send_buffered_data (&dtc_ldsc[i]);

View file

@ -570,7 +570,7 @@ mt_attach(UNIT * uptr, CONST char *file)
{ {
t_stat r; t_stat r;
if ((r = sim_tape_attach(uptr, file)) != SCPE_OK) if ((r = sim_tape_attach_ex(uptr, file, 0, 0)) != SCPE_OK)
return r; return r;
uptr->u5 |= MT_LOADED|MT_BOT; uptr->u5 |= MT_LOADED|MT_BOT;
sim_activate(uptr, 50000); sim_activate(uptr, 50000);

View file

@ -136,7 +136,7 @@ const char ascii_to_con[128] = {
/* Control */ /* Control */
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
/*sp ! " # $ % & ' */ /*sp ! " # $ % & ' */
020, 032, 037, 013, 053, 017, 060, 014, /* 40 - 77 */ 020, 032, 037, 013, 053, 034, 060, 014, /* 40 - 77 */
/* ( ) * + , - . / */ /* ( ) * + , - . / */
075, 055, 054, 072, 033, 040, 073, 021, 075, 055, 054, 072, 033, 040, 073, 021,
/* 0 1 2 3 4 5 6 7 */ /* 0 1 2 3 4 5 6 7 */
@ -150,7 +150,7 @@ const char ascii_to_con[128] = {
/* P Q R S T U V W */ /* P Q R S T U V W */
047, 050, 051, 022, 023, 024, 025, 026, 047, 050, 051, 022, 023, 024, 025, 026,
/* X Y Z [ \ ] ^ _ */ /* X Y Z [ \ ] ^ _ */
027, 030, 031, 075, 036, 055, 057, 000, 027, 030, 031, 074, 036, 036, 057, 000,
/* ` a b c d e f g */ /* ` a b c d e f g */
035, 061, 062, 063, 064, 065, 066, 067, /* 140 - 177 */ 035, 061, 062, 063, 064, 065, 066, 067, /* 140 - 177 */
/* h i j k l m n o */ /* h i j k l m n o */
@ -158,7 +158,7 @@ const char ascii_to_con[128] = {
/* p q r s t u v w */ /* p q r s t u v w */
047, 050, 051, 022, 023, 024, 025, 026, 047, 050, 051, 022, 023, 024, 025, 026,
/* x y z { | } ~ del*/ /* x y z { | } ~ del*/
027, 030, 031, 057, 077, 017, -1, -1 027, 030, 031, 057, 052, 017, -1, -1
}; };
@ -341,9 +341,10 @@ t_opcode char_ops[] = {
/* Print out an instruction */ /* Print out an instruction */
void void
print_opcode(FILE * of, t_value val, t_opcode * tab) print_opcode(FILE * of, t_value val, int chr_mode)
{ {
uint16 op; uint16 op;
t_opcode *tab = (chr_mode) ? char_ops: word_ops;
op = val; op = val;
while (tab->name != NULL) { while (tab->name != NULL) {
@ -410,14 +411,14 @@ fprint_sym(FILE * of, t_addr addr, t_value * val, UNIT * uptr, int32 sw)
fputs(" ", of); fputs(" ", of);
for (i = 36; i >= 0; i-=12) { for (i = 36; i >= 0; i-=12) {
int op = (int)(inst >> i) & 07777; int op = (int)(inst >> i) & 07777;
print_opcode(of, op, word_ops); print_opcode(of, op, 0);
} }
} }
if (sw & SWMASK('C')) { /* Char mode opcodes */ if (sw & SWMASK('C')) { /* Char mode opcodes */
fputs(" ", of); fputs(" ", of);
for (i = 36; i >= 0; i-=12) { for (i = 36; i >= 0; i-=12) {
int op = (int)(inst >> i) & 07777; int op = (int)(inst >> i) & 07777;
print_opcode(of, op, char_ops); print_opcode(of, op, 1);
} }
} }
if (sw & SWMASK('B')) { /* BCD mode */ if (sw & SWMASK('B')) { /* BCD mode */

View file

@ -35,10 +35,6 @@
#define UNIT_CDP UNIT_ATTABLE | UNIT_DISABLE | MODE_029 #define UNIT_CDP UNIT_ATTABLE | UNIT_DISABLE | MODE_029
#define UNIT_LPR UNIT_ATTABLE | UNIT_DISABLE #define UNIT_LPR UNIT_ATTABLE | UNIT_DISABLE
/* For Card reader, when set returns end of file at end of deck. */
/* Reset after sent to system */
#define MODE_EOF (0x40 << UNIT_V_CARD_MODE)
#define TMR_RTC 0 #define TMR_RTC 0
@ -84,6 +80,7 @@ DEBTAB cdr_debug[] = {
#if NUM_DEVS_CDR > 0 #if NUM_DEVS_CDR > 0
t_stat cdr_boot(int32, DEVICE *); t_stat cdr_boot(int32, DEVICE *);
t_stat cdr_ini(DEVICE *);
t_stat cdr_srv(UNIT *); t_stat cdr_srv(UNIT *);
t_stat cdr_attach(UNIT *, CONST char *); t_stat cdr_attach(UNIT *, CONST char *);
t_stat cdr_detach(UNIT *); t_stat cdr_detach(UNIT *);
@ -92,6 +89,7 @@ const char *cdr_description(DEVICE *dptr);
#endif #endif
#if NUM_DEVS_CDP > 0 #if NUM_DEVS_CDP > 0
t_stat cdp_ini(DEVICE *);
t_stat cdp_srv(UNIT *); t_stat cdp_srv(UNIT *);
t_stat cdp_attach(UNIT *, CONST char *); t_stat cdp_attach(UNIT *, CONST char *);
t_stat cdp_detach(UNIT *); t_stat cdp_detach(UNIT *);
@ -106,6 +104,7 @@ struct _lpr_data
} }
lpr_data[NUM_DEVS_LPR]; lpr_data[NUM_DEVS_LPR];
t_stat lpr_ini(DEVICE *);
t_stat lpr_srv(UNIT *); t_stat lpr_srv(UNIT *);
t_stat lpr_attach(UNIT *, CONST char *); t_stat lpr_attach(UNIT *, CONST char *);
t_stat lpr_detach(UNIT *); t_stat lpr_detach(UNIT *);
@ -146,16 +145,14 @@ MTAB cdr_mod[] = {
{MTAB_XTD | MTAB_VUN, 0, "FORMAT", "FORMAT", {MTAB_XTD | MTAB_VUN, 0, "FORMAT", "FORMAT",
&sim_card_set_fmt, &sim_card_show_fmt, NULL, &sim_card_set_fmt, &sim_card_show_fmt, NULL,
"Sets card format"}, "Sets card format"},
{MODE_EOF, MODE_EOF, "EOF", "EOF", NULL, NULL, NULL,
"Causes EOF to be set when reader empty"},
{0} {0}
}; };
DEVICE cdr_dev = { DEVICE cdr_dev = {
"CR", cdr_unit, NULL, cdr_mod, "CR", cdr_unit, NULL, cdr_mod,
NUM_DEVS_CDR, 8, 15, 1, 8, 8, NUM_DEVS_CDR, 8, 15, 1, 8, 8,
NULL, NULL, NULL, &cdr_boot, &cdr_attach, &cdr_detach, NULL, NULL, &cdr_ini, &cdr_boot, &cdr_attach, &cdr_detach,
NULL, DEV_DISABLE | DEV_DEBUG, 0, cdr_debug, NULL, DEV_DISABLE | DEV_DEBUG | DEV_CARD, 0, cdr_debug,
NULL, NULL, &cdr_help, NULL, NULL, NULL, NULL, &cdr_help, NULL, NULL,
&cdr_description &cdr_description
}; };
@ -176,8 +173,8 @@ MTAB cdp_mod[] = {
DEVICE cdp_dev = { DEVICE cdp_dev = {
"CP", cdp_unit, NULL, cdp_mod, "CP", cdp_unit, NULL, cdp_mod,
NUM_DEVS_CDP, 8, 15, 1, 8, 8, NUM_DEVS_CDP, 8, 15, 1, 8, 8,
NULL, NULL, NULL, NULL, &cdp_attach, &cdp_detach, NULL, NULL, &cdp_ini, NULL, &cdp_attach, &cdp_detach,
NULL, DEV_DISABLE | DEV_DEBUG, 0, cdr_debug, NULL, DEV_DISABLE | DEV_DEBUG | DEV_CARD, 0, cdr_debug,
NULL, NULL, &cdp_help, NULL, NULL, NULL, NULL, &cdp_help, NULL, NULL,
&cdp_description &cdp_description
}; };
@ -202,7 +199,7 @@ MTAB lpr_mod[] = {
DEVICE lpr_dev = { DEVICE lpr_dev = {
"LP", lpr_unit, NULL, lpr_mod, "LP", lpr_unit, NULL, lpr_mod,
NUM_DEVS_LPR, 8, 15, 1, 8, 8, NUM_DEVS_LPR, 8, 15, 1, 8, 8,
NULL, NULL, NULL, NULL, &lpr_attach, &lpr_detach, NULL, NULL, &lpr_ini, NULL, &lpr_attach, &lpr_detach,
NULL, DEV_DISABLE | DEV_DEBUG, 0, dev_debug, NULL, DEV_DISABLE | DEV_DEBUG, 0, dev_debug,
NULL, NULL, &lpr_help, NULL, NULL, NULL, NULL, &lpr_help, NULL, NULL,
&lpr_description &lpr_description
@ -217,7 +214,7 @@ UNIT con_unit[] = {
DEVICE con_dev = { DEVICE con_dev = {
"CON", con_unit, NULL, NULL, "CON", con_unit, NULL, NULL,
NUM_DEVS_CON, 8, 15, 1, 8, 8, NUM_DEVS_CON, 8, 15, 1, 8, 8,
NULL, NULL, con_ini, NULL, NULL, NULL, NULL, NULL, &con_ini, NULL, NULL, NULL,
NULL, DEV_DISABLE | DEV_DEBUG, 0, dev_debug, NULL, DEV_DISABLE | DEV_DEBUG, 0, dev_debug,
NULL, NULL, &con_help, NULL, NULL, NULL, NULL, &con_help, NULL, NULL,
&con_description &con_description
@ -227,6 +224,17 @@ DEVICE con_dev = {
#if ((NUM_DEVS_CDR > 0) | (NUM_DEVS_CDP > 0)) #if ((NUM_DEVS_CDR > 0) | (NUM_DEVS_CDP > 0))
t_stat
cdr_ini(DEVICE *dptr) {
int i;
for(i = 0; i < NUM_DEVS_CDR; i++) {
cdr_unit[i].u5 = 0;
sim_cancel(&cdr_unit[i]);
}
return SCPE_OK;
}
/* /*
* Device entry points for card reader. * Device entry points for card reader.
* And Card punch. * And Card punch.
@ -255,16 +263,14 @@ t_stat card_cmd(uint16 cmd, uint16 dev, uint8 chan, uint16 *wc)
/* Check if we ran out of cards */ /* Check if we ran out of cards */
if (uptr->u5 & URCSTA_EOF) { if (uptr->u5 & URCSTA_EOF) {
/* If end of file, return to system */ /* If end of file, return to system */
if (uptr->flags & MODE_EOF) { if (sim_card_input_hopper_count(uptr) != 0)
sim_debug(DEBUG_DETAIL, &cdr_dev, "cdr %d %d report eof\n", u, uptr->u5 &= ~URCSTA_EOF;
chan); else {
chan_set_eof(chan);
uptr->flags &= ~MODE_EOF;
}
/* Clear unit ready */ /* Clear unit ready */
iostatus &= ~(CARD1_FLAG << u); iostatus &= ~(CARD1_FLAG << u);
return SCPE_UNATT; return SCPE_UNATT;
} }
}
if (cmd & URCSTA_BINARY) { if (cmd & URCSTA_BINARY) {
uptr->u5 |= URCSTA_BIN; uptr->u5 |= URCSTA_BIN;
@ -307,6 +313,7 @@ t_stat
cdr_srv(UNIT *uptr) { cdr_srv(UNIT *uptr) {
int chan = URCSTA_CHMASK & uptr->u5; int chan = URCSTA_CHMASK & uptr->u5;
int u = (uptr - cdr_unit); int u = (uptr - cdr_unit);
uint16 *image = (uint16 *)(uptr->up7);
if (uptr->u5 & URCSTA_EOF) { if (uptr->u5 & URCSTA_EOF) {
sim_debug(DEBUG_DETAIL, &cdr_dev, "cdr %d %d unready\n", u, chan); sim_debug(DEBUG_DETAIL, &cdr_dev, "cdr %d %d unready\n", u, chan);
@ -319,32 +326,27 @@ cdr_srv(UNIT *uptr) {
/* Check if new card requested. */ /* Check if new card requested. */
if (uptr->u4 == 0 && uptr->u5 & URCSTA_ACTIVE && if (uptr->u4 == 0 && uptr->u5 & URCSTA_ACTIVE &&
(uptr->u5 & URCSTA_CARD) == 0) { (uptr->u5 & URCSTA_CARD) == 0) {
switch(sim_read_card(uptr)) { switch(sim_read_card(uptr, image)) {
case SCPE_UNATT: case CDSE_EMPTY:
iostatus &= ~(CARD1_FLAG << u); iostatus &= ~(CARD1_FLAG << u);
uptr->u5 &= ~(URCSTA_ACTIVE); uptr->u5 &= ~(URCSTA_ACTIVE);
iostatus &= ~(CARD1_FLAG << u); iostatus &= ~(CARD1_FLAG << u);
chan_set_notrdy(chan); chan_set_notrdy(chan);
break; break;
case SCPE_EOF: case CDSE_EOF:
/* If end of file, return to system */ /* If end of file, return to system */
if (uptr->flags & MODE_EOF) {
sim_debug(DEBUG_DETAIL, &cdr_dev, "cdr %d %d set eof\n", u, chan);
chan_set_eof(chan);
uptr->flags &= ~MODE_EOF;
}
uptr->u5 &= ~(URCSTA_ACTIVE); uptr->u5 &= ~(URCSTA_ACTIVE);
uptr->u5 |= URCSTA_EOF; uptr->u5 |= URCSTA_EOF;
chan_set_notrdy(chan); chan_set_notrdy(chan);
sim_activate(uptr, 500); sim_activate(uptr, 500);
break; break;
case SCPE_IOERR: case CDSE_ERROR:
chan_set_error(chan); chan_set_error(chan);
uptr->u5 &= ~(URCSTA_ACTIVE); uptr->u5 &= ~(URCSTA_ACTIVE);
uptr->u5 |= URCSTA_EOF; uptr->u5 |= URCSTA_EOF;
chan_set_end(chan); chan_set_end(chan);
break; break;
case SCPE_OK: case CDSE_OK:
uptr->u5 |= URCSTA_CARD; uptr->u5 |= URCSTA_CARD;
sim_activate(uptr, 500); sim_activate(uptr, 500);
break; break;
@ -356,22 +358,18 @@ cdr_srv(UNIT *uptr) {
/* Copy next column over */ /* Copy next column over */
if (uptr->u5 & URCSTA_CARD && if (uptr->u5 & URCSTA_CARD &&
uptr->u4 < ((uptr->u5 & URCSTA_BIN) ? 160 : 80)) { uptr->u4 < ((uptr->u5 & URCSTA_BIN) ? 160 : 80)) {
struct _card_data *data;
uint8 ch = 0; uint8 ch = 0;
int u = (uptr - cdr_unit); int u = (uptr - cdr_unit);
data = (struct _card_data *)uptr->up7;
if (uptr->u5 & URCSTA_BIN) { if (uptr->u5 & URCSTA_BIN) {
ch = (data->image[uptr->u4 >> 1] >> ch = (image[uptr->u4 >> 1] >> ((uptr->u4 & 1)? 0 : 6)) & 077;
((uptr->u4 & 1)? 0 : 6)) & 077;
} else { } else {
ch = sim_hol_to_bcd(data->image[uptr->u4]); ch = sim_hol_to_bcd(image[uptr->u4]);
/* Remap some characters from 029 to BCL */ /* Remap some characters from 029 to BCL */
switch(ch) { switch(ch) {
case 0: ch = 020; break; /* Translate blanks */ case 0: ch = 020; break; /* Translate blanks */
case 10: /* Check if 0 punch of 82 punch */ case 10: /* Check if 0 punch of 82 punch */
if (data->image[uptr->u4] != 0x200) { if (image[uptr->u4] != 0x200) {
ch = 0; ch = 0;
if (uptr->u4 == 0) if (uptr->u4 == 0)
chan_set_parity(chan); chan_set_parity(chan);
@ -439,6 +437,8 @@ cdr_attach(UNIT * uptr, CONST char *file)
if ((r = sim_card_attach(uptr, file)) != SCPE_OK) if ((r = sim_card_attach(uptr, file)) != SCPE_OK)
return r; return r;
if (uptr->up7 == 0)
uptr->up7 = malloc(sizeof(uint16)*80);
uptr->u5 &= URCSTA_BUSY; uptr->u5 &= URCSTA_BUSY;
uptr->u4 = 0; uptr->u4 = 0;
uptr->u6 = 0; uptr->u6 = 0;
@ -451,6 +451,9 @@ cdr_detach(UNIT * uptr)
{ {
int u = uptr-cdr_unit; int u = uptr-cdr_unit;
if (uptr->up7 != 0)
free(uptr->up7);
uptr->up7 = 0;
iostatus &= ~(CARD1_FLAG << u); iostatus &= ~(CARD1_FLAG << u);
return sim_card_detach(uptr); return sim_card_detach(uptr);
} }
@ -462,10 +465,6 @@ cdr_help(FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr)
fprintf (st, "The system supports up to two card readers, the second one is disabled\n"); fprintf (st, "The system supports up to two card readers, the second one is disabled\n");
fprintf (st, "by default. To have the card reader return the EOF flag when the deck\n"); fprintf (st, "by default. To have the card reader return the EOF flag when the deck\n");
fprintf (st, "has finished reading do:\n"); fprintf (st, "has finished reading do:\n");
fprintf (st, " sim> SET CRn EOF\n");
fprintf (st, "This flag is cleared each time a deck has been read, so it must be set\n");
fprintf (st, "again after each deck. MCP does not require this to be set as long as\n");
fprintf (st, "the deck includes a ?END card\n");
fprint_set_help(st, dptr); fprint_set_help(st, dptr);
fprint_show_help(st, dptr); fprint_show_help(st, dptr);
return SCPE_OK; return SCPE_OK;
@ -484,27 +483,39 @@ cdr_description(DEVICE *dptr)
#if NUM_DEVS_CDR > 0 | NUM_DEVS_CDP > 0 #if NUM_DEVS_CDR > 0 | NUM_DEVS_CDP > 0
/* Handle transfer of data for card punch */ /* Handle transfer of data for card punch */
t_stat
cdp_ini(DEVICE *dptr) {
int i;
for(i = 0; i < NUM_DEVS_CDP; i++) {
cdp_unit[i].u5 = 0;
sim_cancel(&cdp_unit[i]);
}
return SCPE_OK;
}
t_stat t_stat
cdp_srv(UNIT *uptr) { cdp_srv(UNIT *uptr) {
int chan = URCSTA_CHMASK & uptr->u5; int chan = URCSTA_CHMASK & uptr->u5;
int u = (uptr - cdp_unit); int u = (uptr - cdp_unit);
uint16 *image = (uint16 *)(uptr->up7);
if (uptr->u5 & URCSTA_BUSY) { if (uptr->u5 & URCSTA_BUSY) {
/* Done waiting, punch card */ /* Done waiting, punch card */
if (uptr->u5 & URCSTA_FULL) { if (uptr->u5 & URCSTA_FULL) {
sim_debug(DEBUG_DETAIL, &cdp_dev, "cdp %d %d punch\n", u, chan); sim_debug(DEBUG_DETAIL, &cdp_dev, "cdp %d %d punch\n", u, chan);
switch(sim_punch_card(uptr, NULL)) { switch(sim_punch_card(uptr, image)) {
case SCPE_EOF: case CDSE_EOF:
case SCPE_UNATT: case CDSE_EMPTY:
sim_debug(DEBUG_DETAIL, &cdp_dev, "cdp %d %d set eof\n", u, sim_debug(DEBUG_DETAIL, &cdp_dev, "cdp %d %d set eof\n", u,
chan); chan);
chan_set_eof(chan); chan_set_eof(chan);
break; break;
/* If we get here, something is wrong */ /* If we get here, something is wrong */
case SCPE_IOERR: case CDSE_ERROR:
chan_set_error(chan); chan_set_error(chan);
break; break;
case SCPE_OK: case CDSE_OK:
break; break;
} }
uptr->u5 &= ~URCSTA_FULL; uptr->u5 &= ~URCSTA_FULL;
@ -515,18 +526,15 @@ cdp_srv(UNIT *uptr) {
/* Copy next column over */ /* Copy next column over */
if (uptr->u5 & URCSTA_ACTIVE && uptr->u4 < 80) { if (uptr->u5 & URCSTA_ACTIVE && uptr->u4 < 80) {
struct _card_data *data;
uint8 ch = 0; uint8 ch = 0;
data = (struct _card_data *)uptr->up7;
if(chan_read_char(chan, &ch, 0)) { if(chan_read_char(chan, &ch, 0)) {
uptr->u5 |= URCSTA_BUSY|URCSTA_FULL; uptr->u5 |= URCSTA_BUSY|URCSTA_FULL;
uptr->u5 &= ~URCSTA_ACTIVE; uptr->u5 &= ~URCSTA_ACTIVE;
} else { } else {
sim_debug(DEBUG_DATA, &cdp_dev, "cdp %d: Char %d < %02o\n", u, sim_debug(DEBUG_DATA, &cdp_dev, "cdp %d: Char %d < %02o\n", u,
uptr->u4, ch); uptr->u4, ch);
data->image[uptr->u4++] = sim_bcd_to_hol(ch & 077); image[uptr->u4++] = sim_bcd_to_hol(ch & 077);
} }
sim_activate(uptr, 10); sim_activate(uptr, 10);
} }
@ -547,16 +555,24 @@ cdp_attach(UNIT * uptr, CONST char *file)
if ((r = sim_card_attach(uptr, file)) != SCPE_OK) if ((r = sim_card_attach(uptr, file)) != SCPE_OK)
return r; return r;
if (uptr->up7 == 0) {
uptr->up7 = calloc(80, sizeof(uint16));
uptr->u5 = 0; uptr->u5 = 0;
iostatus |= PUNCH_FLAG; iostatus |= PUNCH_FLAG;
}
return SCPE_OK; return SCPE_OK;
} }
t_stat t_stat
cdp_detach(UNIT * uptr) cdp_detach(UNIT * uptr)
{ {
uint16 *image = (uint16 *)(uptr->up7);
if (uptr->u5 & URCSTA_FULL) if (uptr->u5 & URCSTA_FULL)
sim_punch_card(uptr, NULL); sim_punch_card(uptr, image);
if (uptr->up7 != 0)
free(uptr->up7);
uptr->up7 = 0;
iostatus &= ~PUNCH_FLAG; iostatus &= ~PUNCH_FLAG;
return sim_card_detach(uptr); return sim_card_detach(uptr);
} }
@ -583,6 +599,16 @@ cdp_description(DEVICE *dptr)
/* Line printer routines /* Line printer routines
*/ */
t_stat
lpr_ini(DEVICE *dptr) {
int i;
for(i = 0; i < NUM_DEVS_LPR; i++) {
lpr_unit[i].u5 = 0;
sim_cancel(&lpr_unit[i]);
}
return SCPE_OK;
}
#if NUM_DEVS_LPR > 0 #if NUM_DEVS_LPR > 0
t_stat t_stat

Binary file not shown.