From 1a1396d0bac99ae56b5aa260f3bc1885632becd4 Mon Sep 17 00:00:00 2001 From: Richard Cornwell Date: Sun, 31 Dec 2023 15:38:40 -0500 Subject: [PATCH] I7000: Group update for IBM 7000 series simulators. I7010 updated to pass diagnostics. I7080 updated to pass diagnostics. I7090 updated to better pass 9IOT updated to allow Stress and other applications to run better. Updated card punch to allow input of card decks for overpunching. --- I7000/i7000_cdp.c | 190 +++++++++++++++++++- I7000/i7000_cdr.c | 18 +- I7000/i7000_mt.c | 84 ++++++--- I7000/i7010_chan.c | 58 +++--- I7000/i7010_cpu.c | 288 ++++++++++++++++++------------ I7000/i7080_chan.c | 26 ++- I7000/i7080_cpu.c | 426 +++++++++++++++++++++++++++++---------------- I7000/i7080_defs.h | 4 +- I7000/i7090_cdr.c | 8 +- I7000/i7090_chan.c | 10 +- I7000/i7090_cpu.c | 41 +++-- 11 files changed, 800 insertions(+), 353 deletions(-) diff --git a/I7000/i7000_cdp.c b/I7000/i7000_cdp.c index c1e2cc0a2..f4c63a75c 100644 --- a/I7000/i7000_cdp.c +++ b/I7000/i7000_cdp.c @@ -40,6 +40,12 @@ /* Flags for punch and reader. */ #define ATTENA (1 << (UNIT_V_UF+7)) #define ATTENB (1 << (UNIT_V_UF+14)) +#define INPUT_V (UNIT_V_UF+7) +#define INPUT_FULL (1 << INPUT_V) +#define INPUT_EMPTY (2 << INPUT_V) +#define INPUT_DECK (3 << INPUT_V) +#define INPUT_BLANK (4 << INPUT_V) +#define INPUT_MASK (7 << INPUT_V) /* std devices. data structures @@ -56,6 +62,8 @@ t_stat cdp_srv(UNIT *); t_stat cdp_reset(DEVICE *); t_stat cdp_attach(UNIT *, CONST char *); t_stat cdp_detach(UNIT *); +t_stat cdp_get_input(FILE *, UNIT *, int32, CONST void *); +t_stat cdp_set_input(UNIT *, int32, CONST char *, void *); t_stat cdp_help(FILE *, DEVICE *, UNIT *, int32, const char *); const char *cdp_description(DEVICE *dptr); t_stat stk_help(FILE *, DEVICE *, UNIT *, int32, const char *); @@ -68,6 +76,13 @@ UNIT cdp_unit[] = { #endif }; +UNIT cdp_input_unit[] = { + {UDATA(NULL, UNIT_ATTABLE | INPUT_FULL | UNIT_RO, 0), 600}, /* A */ +#if NUM_DEVS_CDP > 1 + {UDATA(NULL, UNIT_ATTABLE | INPUT_FULL | UNIT_RO, 0), 600}, /* B */ +#endif +}; + MTAB cdp_mod[] = { {MTAB_XTD | MTAB_VUN, 0, "FORMAT", "FORMAT", &sim_card_set_fmt, &sim_card_show_fmt, NULL, "Set card format"}, @@ -80,17 +95,27 @@ MTAB cdp_mod[] = { {MTAB_XTD | MTAB_VUN | MTAB_VALR, 0, "CHAN", "CHAN", &set_chan, &get_chan, NULL, "Set device channel"}, #endif + {MTAB_XTD | MTAB_VUN | MTAB_VALR | MTAB_NC, 0, "INPUT", "INPUT", &cdp_set_input, &cdp_get_input, + NULL, "Set input to card punch"}, {0} }; DEVICE cdp_dev = { "CDP", cdp_unit, NULL, cdp_mod, NUM_DEVS_CDP, 8, 15, 1, 8, 8, - NULL, NULL, NULL, NULL, &cdp_attach, &cdp_detach, + NULL, NULL, &cdp_reset, NULL, &cdp_attach, &cdp_detach, &cdp_dib, DEV_DISABLE | DEV_DEBUG | DEV_CARD, 0, crd_debug, NULL, NULL, &cdp_help, NULL, NULL, &cdp_description }; +DEVICE cdp_input_dev = { + "INPUT", cdp_input_unit, NULL, NULL, + NUM_DEVS_CDP, 8, 15, 1, 8, 8, + NULL, NULL, NULL, NULL, NULL, NULL, + NULL, DEV_DISABLE | DEV_DIS, 0, NULL, + NULL, NULL, NULL, NULL, NULL, NULL +}; + #ifdef STACK_DEV UNIT stack_unit[] = { { UDATA (NULL, UNIT_SEQ+UNIT_ATTABLE, 0) }, @@ -140,10 +165,15 @@ uint32 cdp_cmd(UNIT * uptr, uint16 cmd, uint16 dev) int chan = UNIT_G_CHAN(uptr->flags); int u = (uptr - cdp_unit); int stk = dev & 017; + UNIT *iuptr = &cdp_input_unit[u]; + uint16 *image = (uint16 *)(uptr->up7); + int i; /* Are we currently tranfering? */ - if (uptr->u5 & URCSTA_WRITE) + if (uptr->u5 & URCSTA_WRITE) { + sim_debug(DEBUG_DETAIL, &cdp_dev, "%d: Busy\n", u); return SCPE_BUSY; + } if (stk == 10) stk = 0; @@ -173,6 +203,37 @@ uint32 cdp_cmd(UNIT * uptr, uint16 cmd, uint16 dev) uptr->u5 |= stk << 16; #endif sim_debug(DEBUG_CMD, &cdp_dev, "%d: Cmd WRS\n", u); + + switch((iuptr->flags & INPUT_MASK) >> INPUT_V) { + case INPUT_EMPTY >> INPUT_V: + case INPUT_BLANK >> INPUT_V: + if (iuptr->u3 == 0) { + sim_debug(DEBUG_DETAIL, &cdp_dev, "%d: Empty\n", u); + return SCPE_IOERR; + } + iuptr->u3--; + /* Fall through */ + + case INPUT_FULL >> INPUT_V: + for (i = 0; i < 80; image[i++] = 0); + break; + case INPUT_DECK >> INPUT_V: + switch(sim_read_card(iuptr, image)) { + case CDSE_ERROR: + uptr->u5 |= URCSTA_ERR; + /* Fall through */ + + case CDSE_EOF: + case CDSE_EMPTY: + sim_debug(DEBUG_DETAIL, &cdp_dev, "%d: Empty deck\n", u); + return SCPE_IOERR; + case CDSE_OK: + sim_debug(DEBUG_DETAIL, &cdp_dev, "%d: left %d\n", u, + sim_card_input_hopper_count(iuptr)); + break; + } + break; + } chan_set_sel(chan, 1); uptr->u5 |= URCSTA_WRITE; uptr->u4 = 0; @@ -180,7 +241,6 @@ uint32 cdp_cmd(UNIT * uptr, uint16 cmd, uint16 dev) sim_activate(uptr, 50); return SCPE_OK; } - chan_set_attn(chan); return SCPE_IOERR; } @@ -257,9 +317,12 @@ cdp_srv(UNIT *uptr) { ch = 020; else if (ch == 020) ch = 0; - sim_debug(DEBUG_DATA, &cdp_dev, "%d: Char < %02o\n", u, ch); - image[uptr->u4++] = sim_bcd_to_hol(ch); - if (uptr->u4 == 80) { + image[uptr->u4] |= sim_bcd_to_hol(ch); + if (sim_hol_to_bcd(image[uptr->u4]) == 0x7f) { + chan_set_eof(chan); + } + sim_debug(DEBUG_DATA, &cdp_dev, "%d: Char < %02o %04o\n", u, ch, image[uptr->u4]); + if (++uptr->u4 == 80) { chan_set(chan, DEV_REOR); uptr->u5 |= URCSTA_WDISCO|URCSTA_BUSY|URCSTA_FULL; uptr->u5 &= ~URCSTA_WRITE; @@ -271,6 +334,10 @@ cdp_srv(UNIT *uptr) { return SCPE_OK; } +t_stat +cdp_reset(DEVICE *dptr) { + return sim_register_internal_device (&cdp_input_dev); +} void cdp_ini(UNIT *uptr, t_bool f) { @@ -285,7 +352,7 @@ cdp_attach(UNIT * uptr, CONST char *file) if ((r = sim_card_attach(uptr, file)) != SCPE_OK) return r; if (uptr->up7 == 0) { - uptr->up7 = calloc(80, sizeof(uint16)); + uptr->up7 = calloc(80, sizeof(uint16)); uptr->u5 = 0; } return SCPE_OK; @@ -306,12 +373,119 @@ cdp_detach(UNIT * uptr) sim_punch_card(uptr, image); #endif } - if (uptr->up7 == 0) + if (uptr->up7 == 0) free(uptr->up7); uptr->up7 = 0; return sim_card_detach(uptr); } +t_stat +cdp_set_input(UNIT *uptr, int32 val, CONST char *cptr, void *desc) +{ + int nflag = 1; + int num = 0; + char gbuf[30]; + char *p; + int u = (uptr - cdp_unit); + UNIT *iuptr = &cdp_input_unit[u]; + t_stat r = SCPE_ARG; + + if (cptr == NULL) + return SCPE_ARG; + if (uptr == NULL) + return SCPE_IERR; + + /* Clear existing input */ + sim_card_detach(iuptr); + iuptr->u3 = 0; + iuptr->flags &= ~INPUT_MASK; + iuptr->flags |= INPUT_EMPTY; + + /* Get first argument */ + cptr = get_glyph(cptr, gbuf, ';'); + + /* Check if it is a number */ + for (p = gbuf; *p != '\0'; p++) { + if (*p < '0' || *p > '9') { + nflag = 0; + break; + } + num = (num * 10) + (*p) - '0'; + } + + /* If valid number, set to number of blank cards */ + if (nflag) { + iuptr->u3 = num; + iuptr->flags &= ~INPUT_MASK; + iuptr->flags |= INPUT_BLANK; + return SCPE_OK; + } + + /* Check for given format */ + if (sim_strcasecmp(gbuf, "EMPTY") == 0) { + iuptr->u3 = 0; + iuptr->flags &= ~INPUT_MASK; + iuptr->flags |= INPUT_EMPTY; + return SCPE_OK; + } + + if (sim_strcasecmp(gbuf, "FULL") == 0) { + iuptr->u3 = 0; + iuptr->flags &= ~INPUT_MASK; + iuptr->flags |= INPUT_FULL; + return SCPE_OK; + } + + /* If deck attach it to input */ + if (sim_strcasecmp(gbuf, "DECK") == 0) { + int32 saved_switches = sim_switches; + + sim_switches = SWMASK('E') | SWMASK('R'); + if ((saved_switches & SWMASK('F')) != 0) { + cptr = get_glyph(cptr, gbuf, ';'); + sim_card_set_fmt(iuptr, 0, gbuf, NULL); + } + r = sim_card_attach(iuptr, cptr); + if (r == SCPE_OK) { + iuptr->flags &= ~INPUT_MASK; + iuptr->flags |= INPUT_DECK; + } + sim_switches = saved_switches; + } + /* Error, set to empty */ + return r; +} + +t_stat +cdp_get_input(FILE *st, UNIT *uptr, int32 v, CONST void *desc) +{ + int u = (uptr - cdp_unit); + UNIT *iuptr = &cdp_input_unit[u]; + int i; + + if (uptr == NULL) + return SCPE_IERR; + + i = (iuptr->flags & INPUT_MASK) >> INPUT_V; + switch((iuptr->flags & INPUT_MASK) >> INPUT_V) { + case INPUT_BLANK >> INPUT_V: + fprintf(st, "%d blanks", iuptr->u3); + break; + case INPUT_FULL >> INPUT_V: + fprintf(st, "full"); + break; + case INPUT_EMPTY >> INPUT_V: + fprintf(st, "empty"); + break; + case INPUT_DECK >> INPUT_V: + fprintf(st, "deck %s", iuptr->filename); + break; + } + return SCPE_OK; +} + + + #ifdef STACK_DEV t_stat stk_help(FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr) diff --git a/I7000/i7000_cdr.c b/I7000/i7000_cdr.c index 39c355f2f..2c4923dfc 100644 --- a/I7000/i7000_cdr.c +++ b/I7000/i7000_cdr.c @@ -122,8 +122,10 @@ uint32 cdr_cmd(UNIT * uptr, uint16 cmd, uint16 dev) uptr->u5 &= ~0xF0000; uptr->u5 |= stk << 16; #endif - if (uptr->u5 & (URCSTA_EOF|URCSTA_ERR)) + if (uptr->u5 & (URCSTA_EOF|URCSTA_ERR)) { + uptr->u5 &= ~(URCSTA_EOF|URCSTA_ERR); return SCPE_IOERR; + } /* Process commands */ switch(cmd) { @@ -141,15 +143,19 @@ uint32 cdr_cmd(UNIT * uptr, uint16 cmd, uint16 dev) #endif break; default: + sim_debug(DEBUG_CMD, &cdr_dev, "%d: CMD none %02o\n", u, cmd); chan_set_attn(chan); return SCPE_IOERR; } /* If at eof, just return EOF */ - if (uptr->u5 & URCSTA_EOF) { + if (sim_card_eof(uptr)) { + uint16 *image = (uint16 *)(uptr->up7); chan_set_eof(chan); chan_set_attn(chan); - return SCPE_OK; + uptr->u5 &= ~(URCSTA_EOF|URCSTA_ERR); + (void)sim_read_card(uptr, image); + return SCPE_IOERR; } uptr->u5 |= URCSTA_READ; @@ -256,6 +262,10 @@ cdr_srv(UNIT *uptr) { #endif ch = sim_hol_to_bcd(image[uptr->u4]); + /* Handle 7-9 to generate 20 */ + if (ch == 012 && image[uptr->u4] == 0202) { + ch = 020; + } /* Handle invalid punch */ if (ch == 0x7f) { @@ -288,7 +298,7 @@ cdr_srv(UNIT *uptr) { uptr->u4++; break; } - sim_debug(DEBUG_DATA, &cdr_dev, "%d: Char > %02o\n", u, ch); + sim_debug(DEBUG_DATA, &cdr_dev, "%d: Char > %04o %02o\n", u, image[uptr->u4-1], ch); sim_activate(uptr, 10); } return SCPE_OK; diff --git a/I7000/i7000_mt.c b/I7000/i7000_mt.c index 28e203513..ab62bf94c 100644 --- a/I7000/i7000_mt.c +++ b/I7000/i7000_mt.c @@ -78,6 +78,8 @@ #define MT_EOR 002000 /* Set EOR on next record */ #define MT_UNLOAD 004000 /* Unload when rewind done */ #define MT_EGAP 010000 /* Write extended gap on next write */ +#define MT_LWR 020000 /* Last command was a write */ +#define MT_CLRIND 040000 /* On I7010 flag for SKR to clear indicator */ /* u6 holds the current buffer position */ @@ -90,8 +92,8 @@ #define IPS 75 /* Inches per second 75 or 112 */ #define HS_IPS 500 /* High speed rewind Inches per second */ -#define LD 200 -#define HD 555 +#define LD 300 +#define HD 150 #define LT_GAP_LEN ((3 * LD)/ 4) /* Gap length for low density */ #define HT_GAP_LEN ((3 * HD)/ 4) /* Gap length for high density */ @@ -238,9 +240,9 @@ UNIT mta_unit[] = { }; MTAB mt_mod[] = { - { MTAB_XTD|MTAB_VUN, 0, "write enabled", "WRITEENABLED", + { MTAB_XTD|MTAB_VUN, 0, "write enabled", "WRITEENABLED", &set_writelock, &show_writelock, NULL, "Write ring in place" }, - { MTAB_XTD|MTAB_VUN, 1, NULL, "LOCKED", + { MTAB_XTD|MTAB_VUN, 1, NULL, "LOCKED", &set_writelock, NULL, NULL, "no Write ring in place" }, {MTUF_LDN, 0, "high density", "HIGH", &mt_tape_density, NULL, NULL, "556 BPI"}, @@ -393,7 +395,7 @@ uint32 mt_cmd(UNIT * uptr, uint16 cmd, uint16 dev) /* If drive is offline or not attached return not ready */ if ((uptr->flags & (UNIT_ATT | MTUF_ONLINE)) != (UNIT_ATT | MTUF_ONLINE)) { - sim_printf("Attempt to access offline unit %s%d\n\r", dptr->name, unit); + sim_messagef(SCPE_OK, "Attempt to access offline unit %s%d\n\r", dptr->name, unit); return SCPE_IOERR; } /* Check if drive is ready to recieve a command */ @@ -798,6 +800,7 @@ t_stat mt_srv(UNIT * uptr) switch (cmd) { case 0: /* No command, stop tape */ uptr->u5 |= MT_RDY; /* Ready since command is done */ + mt_chan[chan] &= ~MTC_BSY; sim_debug(DEBUG_DETAIL, dptr, "Idle unit=%d\n", unit); return SCPE_OK; @@ -820,6 +823,7 @@ t_stat mt_srv(UNIT * uptr) /* Fall through */ case MT_RDSB: + uptr->u5 &= ~MT_LWR; /* Not write command */ /* Post EOR */ if (uptr->u5 & MT_EOR) { sim_debug(DEBUG_DETAIL, dptr, "Read unit=%d post EOR\n", unit); @@ -900,13 +904,14 @@ t_stat mt_srv(UNIT * uptr) uptr->u3++; /* Do BCD translation */ if ((parity_table[ch & 077] ^ (ch & 0100) ^ mode) == 0) { + sim_debug(DEBUG_DETAIL, dptr, "%s parity error %d %03o\n", + (cmd == MT_RDS) ? "BCD" : "Binary", uptr->u3-1, ch); #ifdef I7010 if (astmode) ch = 054; -#else - chan_set_attn(chan); #endif chan_set_error(chan); + } #if I7090 | I704 | I701 /* Not needed on decimal machines */ @@ -972,6 +977,7 @@ t_stat mt_srv(UNIT * uptr) mode = 0100; /* fall through */ case MT_WRSB: + uptr->u5 |= MT_LWR; /* write command */ if (uptr->u5 & MT_EGAP) { sim_debug(DEBUG_DETAIL, dptr, "Write extended Gap unit=%d\n", unit); uptr->u5 &= ~MT_EGAP; @@ -984,6 +990,8 @@ t_stat mt_srv(UNIT * uptr) (uptr->u6 > BUFFSIZE) ? DEV_WEOR : 0)) { case TIME_ERROR: #if I7090 | I701 | I704 + uptr->u5 &= ~MT_CMDMSK; + uptr->u5 |= MT_SKIP; /* If no data was written, simulate a write gap */ if (uptr->u6 == 0) { r = sim_tape_wrgap(uptr, 35); @@ -993,7 +1001,6 @@ t_stat mt_srv(UNIT * uptr) } } #endif - chan_set_attn(chan); /* fall through */ case END_RECORD: @@ -1034,6 +1041,7 @@ t_stat mt_srv(UNIT * uptr) return SCPE_OK; case MT_RDB: + uptr->u5 &= ~MT_LWR; /* not write command */ /* If tape mark pending, return it */ if (chan_test(chan, DEV_FULL) == 0 && uptr->u5 & MT_MARK) { sim_debug(DEBUG_DETAIL, dptr, "Read unit=%d post ", unit); @@ -1116,6 +1124,7 @@ t_stat mt_srv(UNIT * uptr) return SCPE_OK; case MT_WEF: + uptr->u5 &= ~MT_LWR; /* not write command */ if (uptr->u5 & MT_EGAP) { sim_debug(DEBUG_DETAIL, dptr, "Write extended Gap unit=%d\n", unit); uptr->u5 &= ~MT_EGAP; @@ -1137,8 +1146,17 @@ t_stat mt_srv(UNIT * uptr) case MT_BSR: sim_debug(DEBUG_DETAIL, dptr, "Backspace rec unit=%d ", unit); + /* If last command was a write, put extended gap on tape */ + if (uptr->u5 & MT_LWR) { + sim_debug(DEBUG_DETAIL, dptr, "Write extended Gap unit=%d bsr\n", unit); + r = sim_tape_wrgap(uptr, 35); + uptr->u5 &= ~MT_LWR; + sim_activate(uptr, 10*T3_us); + return SCPE_OK; + } + /* Clear tape mark, command, idle since we will need to change dir */ - uptr->u5 &= ~(MT_CMDMSK | MT_EOT | MT_RDY); + uptr->u5 &= ~(MT_CMDMSK | MT_EOT | MT_RDY | MT_LWR); r = sim_tape_sprecr(uptr, &reclen); if (r != MTSE_BOT) uptr->u3 -= GAP_LEN; @@ -1146,8 +1164,6 @@ t_stat mt_srv(UNIT * uptr) if (r == MTSE_TMK) { #ifdef I7080 chan_set_eof(chan); -#else - /* We don't set EOF on BSR */ #endif sim_debug(DEBUG_DETAIL, dptr, "MARK\n"); sim_activate(uptr, T2_us); @@ -1159,7 +1175,7 @@ t_stat mt_srv(UNIT * uptr) return SCPE_OK; case MT_BSF: - uptr->u5 &= ~(MT_IDLE | MT_RDY | MT_EOT); + uptr->u5 &= ~(MT_IDLE | MT_RDY | MT_EOT | MT_LWR); r = sim_tape_sprecr(uptr, &reclen); if (r != MTSE_BOT) uptr->u3 -= GAP_LEN; @@ -1171,45 +1187,54 @@ t_stat mt_srv(UNIT * uptr) sim_activate(uptr, T2_us); } else { uptr->u3 -= reclen; + sim_debug(DEBUG_DETAIL, dptr, "Backspace file record unit=%d\n", unit); sim_activate(uptr, T2_us + (reclen * T1_us)); } return SCPE_OK; case MT_SKR: sim_debug(DEBUG_DETAIL, dptr, "Skip rec unit=%d ", unit); - /* Clear tape mark, command, idle since we will need to change dir */ - uptr->u5 &= ~(MT_CMDMSK | MT_EOT); - uptr->u5 |= (MT_RDY | MT_IDLE); + if (uptr->u5 & MT_CLRIND) { + sim_debug(DEBUG_DETAIL, dptr, "clear ind\n"); +#if I7010 + if ((uptr->u5 & MT_MARK) == 0) { + chan_clear(chan, STA_PEND); + } +#endif + chan_clear(chan, STA_TWAIT); + uptr->u5 &= ~(MT_CMDMSK | MT_EOT | MT_LWR | MT_MARK | MT_CLRIND); + uptr->u5 |= (MT_RDY | MT_IDLE); + mt_chan[chan] &= ~MTC_BSY; + sim_activate(uptr, (uptr->u6 * T1_us) + T2_us); + return SCPE_OK; + } + uptr->u5 |= (MT_CLRIND); r = sim_tape_sprecf(uptr, &reclen); uptr->u3 += GAP_LEN; - mt_chan[chan] &= ~MTC_BSY; -#if I7010 | I7080 + uptr->u6 = reclen; +#if I7080 chan_clear(chan, STA_TWAIT); #endif #ifdef I7010 chan_set(chan, STA_PEND); -#else +#endif /* We are like read that transfers nothing */ chan_set(chan, DEV_REOR); -#endif /* We don't set EOF on SKR */ if (r == MTSE_TMK) { sim_debug(DEBUG_DETAIL, dptr, "MARK\n"); - sim_activate(uptr, T1_us); + uptr->u5 |= MT_MARK; + uptr->u6 = 1; + sim_activate(uptr, 2*T1_us); return SCPE_OK; -#ifdef I7010 - } else if (r == MTSE_EOM) { - chan_set(chan, STA_PEND); -#endif } sim_debug(DEBUG_DETAIL, dptr, "%d\n", reclen); - uptr->u3 += reclen; - sim_activate(uptr, (reclen * T1_us)); + sim_activate(uptr, 2*T1_us); break; case MT_ERG: sim_debug(DEBUG_DETAIL, dptr, "Erase unit=%d\n", unit); - uptr->u5 &= ~(MT_CMDMSK|MT_MARK); + uptr->u5 &= ~(MT_CMDMSK|MT_MARK|MT_LWR); uptr->u5 |= (MT_RDY | MT_IDLE); #if I7010 | I7080 chan_clear(chan, STA_TWAIT); @@ -1223,7 +1248,7 @@ t_stat mt_srv(UNIT * uptr) case MT_REW: sim_debug(DEBUG_DETAIL, dptr, "Rewind unit=%d %d %d\n", unit, uptr->u3, uptr->u3 / ((uptr->flags & MTUF_LDN) ? 200 : 555) / 1200); - uptr->u5 &= ~(MT_CMDMSK | MT_IDLE | MT_RDY); + uptr->u5 &= ~(MT_CMDMSK | MT_IDLE | MT_RDY | MT_LWR); if ((uptr->u3 / ((uptr->flags & MTUF_LDN) ? 200 : 555) / 1200) > 2) { uptr->u5 |= MT_HREW; sim_activate(uptr, us_to_ticks(5000000)); @@ -1236,7 +1261,7 @@ t_stat mt_srv(UNIT * uptr) case MT_RUN: sim_debug(DEBUG_DETAIL, dptr, "Unload unit=%d\n", unit); - uptr->u5 &= ~(MT_CMDMSK | MT_IDLE | MT_RDY); + uptr->u5 &= ~(MT_CMDMSK | MT_IDLE | MT_RDY | MT_LWR); uptr->u5 |= MT_UNLOAD; if ((uptr->u3 / ((uptr->flags & MTUF_LDN) ? 200 : 555) / 1200) > 2) { uptr->u5 |= MT_HREW; @@ -1348,6 +1373,7 @@ mt_attach(UNIT * uptr, CONST char *file) if ((r = sim_tape_attach_ex(uptr, file, 0, 0)) != SCPE_OK) return r; + sim_tape_set_dens(uptr, (uptr->flags == MTUF_LDN) ? MT_DENS_200 : MT_DENS_556, NULL, NULL); uptr->u3 = 0; uptr->u5 |= MT_RDY; uptr->flags |= MTUF_ONLINE; diff --git a/I7000/i7010_chan.c b/I7000/i7010_chan.c index 4b936adf4..6b75cf290 100644 --- a/I7000/i7010_chan.c +++ b/I7000/i7010_chan.c @@ -371,33 +371,30 @@ chan_proc() /* If device put up EOR, terminate transfer. */ if (chan_flags[chan] & DEV_REOR) { + sim_debug(DEBUG_DETAIL, &chan_dev, "chan %d EOR %02o Check\n", + chan, chan_io_status[chan]); if (chan_flags[chan] & DEV_WRITE) { if ((cmd[chan] & (CHAN_LOAD|CHAN_WM)) == (CHAN_WM|CHAN_LOAD)) M[caddr[chan]++] = 035; caddr[chan]++; - } else { + } else if ((chan_flags[chan] & (CTL_READ|CTL_WRITE)) != 0) { if ((cmd[chan] & CHAN_NOREC) == 0 && (chan_flags[chan] & STA_WAIT) == 0) { if (MEM_ADDR_OK(caddr[chan])) { - if (M[caddr[chan]++] != (WM|077)) { - if (MEM_ADDR_OK(caddr[chan])) { - chan_io_status[chan] |= IO_CHS_WRL; - if (!MEM_ADDR_OK(caddr[chan]+1)) { - caddr[chan]++; - } - } + uint8 ch = M[caddr[chan]++]; + if (ch != (WM|077)) { + sim_debug(DEBUG_DETAIL, &chan_dev, "chan %d WRL\n", chan); + chan_io_status[chan] |= IO_CHS_WRL; } - } else { - chan_io_status[chan] |= IO_CHS_WRL; - } - } - if ((cmd[chan] & CHAN_NOREC) && MEM_ADDR_OK(caddr[chan])) { - chan_io_status[chan] |= IO_CHS_WRL; - if (!MEM_ADDR_OK(caddr[chan]+1)) { - chan_io_status[chan] &= ~IO_CHS_WRL; } - caddr[chan]++; - } + } + if ((cmd[chan] & CHAN_NOREC) && MEM_ADDR_OK(caddr[chan])) { + chan_io_status[chan] |= IO_CHS_WRL; + if (!MEM_ADDR_OK(caddr[chan]+1)) { + chan_io_status[chan] &= ~IO_CHS_WRL; + } + caddr[chan]++; + } } chan_flags[chan] &= ~(STA_ACTIVE|STA_WAIT|DEV_WRITE|DEV_REOR); chan_io_status[chan] |= IO_CHS_DONE; @@ -460,6 +457,7 @@ chan_cmd(uint16 dev, uint16 dcmd, uint32 addr) /* Unit is busy doing something, wait */ if (chan_flags[chan] & (DEV_SEL|DEV_DISCO|STA_TWAIT|STA_WAIT|STA_ACTIVE)) return SCPE_BUSY; + sim_debug(DEBUG_CMD, &chan_dev, "chan %d %o cmd %02o %d\n", chan, dev, dcmd, addr); /* Ok, try and find the unit */ caddr[chan] = addr; assembly[chan] = 0; @@ -509,6 +507,7 @@ chan_cmd(uint16 dev, uint16 dcmd, uint32 addr) chan_flags[chan] |= STA_ACTIVE; return r; } + /* Handle com device special also */ if ((com_dib.mask & dev) == (com_dib.addr & com_dib.mask)) { switch(dcmd) { case IO_RDS: chan_flags[chan] |= CTL_READ; break; @@ -525,6 +524,12 @@ chan_cmd(uint16 dev, uint16 dcmd, uint32 addr) } r = chan_issue_cmd(chan, dcmd, dev); + switch(dcmd) { + case IO_RDS: chan_flags[chan] |= CTL_READ; break; + case IO_WRS: chan_flags[chan] |= CTL_WRITE; break; + case IO_TRS: chan_flags[chan] |= CTL_SNS; break; + case IO_CTL: chan_flags[chan] |= CTL_CNTL; break; + } /* Activate channel if select raised */ if (chan_flags[chan] & DEV_SEL) { chan_flags[chan] |= STA_ACTIVE; @@ -560,11 +565,11 @@ chan_write_char(int chan, uint8 * data, int flags) { uint8 ch = *data; - sim_debug(DEBUG_DATA, &chan_dev, "chan %d char %o %d %o %o\n", chan, - *data, caddr[chan], chan_io_status[chan], flags); + sim_debug(DEBUG_DATA, &chan_dev, "write chan %d char %o %d %o %o %o\n", chan, + *data, caddr[chan], M[caddr[chan]], chan_io_status[chan], flags); if (chan_flags[chan] & STA_WAIT) { - sim_debug(DEBUG_DETAIL, &chan_dev, "chan %d setWR %d %o\n", chan, + sim_debug(DEBUG_DETAIL, &chan_dev, "chan %d setWRL %d %o\n", chan, caddr[chan], chan_io_status[chan]); chan_io_status[chan] |= IO_CHS_WRL; return END_RECORD; @@ -586,8 +591,7 @@ chan_write_char(int chan, uint8 * data, int flags) chan_flags[chan] |= DEV_REOR; if (chan_flags[chan] & DEV_SEL) chan_flags[chan] |= DEV_DISCO; - chan_io_status[chan] |= IO_CHS_DONE; - caddr[chan]++; + chan_io_status[chan] |= IO_CHS_DONE|IO_CHS_WRL; sim_debug(DEBUG_DETAIL, &chan_dev, "chan %d past mem %d %o\n", chan, caddr[chan], chan_io_status[chan]); chan_flags[chan] &= ~(DEV_WRITE|STA_ACTIVE); @@ -630,6 +634,8 @@ int chan_read_char(int chan, uint8 * data, int flags) { + sim_debug(DEBUG_DATA, &chan_dev, "read chan %d char %o %d %o %o\n", chan, + M[caddr[chan]], caddr[chan], chan_io_status[chan], flags); /* Return END_RECORD if requested */ if (flags & DEV_WEOR) { chan_flags[chan] &= ~(DEV_WEOR); @@ -656,11 +662,11 @@ chan_read_char(int chan, uint8 * data, int flags) *data = assembly[chan]; cmd[chan] &= ~CHAN_WM; } else { - if (!MEM_ADDR_OK(caddr[chan]+1)) { + if (!MEM_ADDR_OK(caddr[chan])) { chan_flags[chan] &= ~STA_ACTIVE; if (chan_flags[chan] & DEV_SEL) chan_flags[chan] |= DEV_DISCO; - caddr[chan]++; + chan_io_status[chan] |= IO_CHS_DONE; return END_RECORD; } assembly[chan] = M[caddr[chan]++]; @@ -670,6 +676,7 @@ chan_read_char(int chan, uint8 * data, int flags) if (chan_flags[chan] & DEV_SEL) chan_flags[chan] |= DEV_DISCO; chan_io_status[chan] |= IO_CHS_DONE; + sim_debug(DEBUG_DATA, &chan_dev, "read return EOR %d\n", chan); return END_RECORD; } if (cmd[chan] & CHAN_LOAD && @@ -691,6 +698,7 @@ chan_read_char(int chan, uint8 * data, int flags) chan_flags[chan] |= DEV_DISCO; chan_io_status[chan] |= IO_CHS_DONE; chan_flags[chan] |= DEV_REOR; + sim_debug(DEBUG_DATA, &chan_dev, "read return EOR2 %d\n", chan); return END_RECORD; } else chan_flags[chan] |= DEV_WRITE; diff --git a/I7000/i7010_cpu.c b/I7000/i7010_cpu.c index e4aaf027e..8f0c2f8b0 100644 --- a/I7000/i7010_cpu.c +++ b/I7000/i7010_cpu.c @@ -409,6 +409,10 @@ void WriteP(uint32 MA, uint8 v) { if (fault) return; + + if (MA == 275) { + int x = v+1; + } if (reloc && (MA & BBIT) == 0 && MAR > 100) { if (low_addr > 0) { MAR += low_addr; @@ -596,7 +600,7 @@ sim_instr(void) if (hst_lnt) /* History enabled? */ hst[hst_p].bend = BAR; } - chan_io_status[chwait & 07] &= ~0100; + chan_io_status[chwait & 07] &= ~IO_CHS_DONE; chwait = 0; } } @@ -1198,7 +1202,7 @@ sim_instr(void) case OP_IO4: /* Not in protected mode */ if (prot_enb || reloc) { - reason = STOP_PROG; + reason = STOP_IOCHECK; break; } case OP_STS: @@ -1242,10 +1246,6 @@ sim_instr(void) break; case OP_UC: /* Not in protected mode */ - if (prot_enb || reloc) { - reason = STOP_PROG; - break; - } /* Valid forms */ /* Op xxx mod */ @@ -1323,8 +1323,10 @@ sim_instr(void) if (cpu_unit.flags & OPTION_PRIO && (pri_enb || timer_enable)) { int irq = inquiry; int ok_irq = 0; + for(i = 1; i < NUM_CHAN; i++ ) { - if ((chan_io_status[i] & 0300) == 0300 && + if ((chan_io_status[i] & (IO_CHS_OVER|IO_CHS_DONE)) + == (IO_CHS_OVER|IO_CHS_DONE) && chan_irq_enb[i]) irq = 1; if (chan_test(i, SNS_ATTN1)) @@ -1333,7 +1335,6 @@ sim_instr(void) irq = 1; } - if (irq || (timer_enable && timer_irq == 1)) { /* Check if we can interupt this opcode */ switch(op) { @@ -1387,24 +1388,25 @@ sim_instr(void) } if (ok_irq) { - sim_debug(DEBUG_PRIO, &cpu_dev, "Irq IAR=%d\n",IAR); prot_enb = reloc = 0; if (pri_enb && irq) { + sim_debug(DEBUG_PRIO, &cpu_dev, "Irq=%d\n",IAR); IAR = temp; AAR = 101; op = OP_PRI; - op_mod = CHR_X; /* X */ + op_mod = CHR_X; if (hst_lnt) { /* History enabled? */ hst[hst_p].inst[0] = op; hst[hst_p].inst[1] = op_mod; hst[hst_p].inst[2] = WM; } } else if (timer_enable && timer_irq == 1) { + sim_debug(DEBUG_PRIO, &cpu_dev, "Tim=%d\n",IAR); IAR = temp; AAR = 301; timer_irq = 2; op = OP_PRI; - op_mod = CHR_X; /* X */ + op_mod = CHR_X; if (hst_lnt) { /* History enabled? */ hst[hst_p].inst[0] = op; hst[hst_p].inst[1] = op_mod; @@ -1980,20 +1982,16 @@ sim_instr(void) case CHR_STAR: /* * Inq req ch 2 */ break; case CHR_1: /* 1 Overlap in Proc Ch 1 */ - jump = ((chan_io_status[1] & 0300) == 0200) && - chan_active(1); + jump = chan_active(1); break; case CHR_2: /* 2 Overlap in Proc Ch 2 */ - jump = ((chan_io_status[2] & 0300) == 0200) && - chan_active(2); + jump = chan_active(2); break; case CHR_4: /* 4 Channel 3 */ - jump = ((chan_io_status[3] & 0300) == 0200) && - chan_active(3); + jump = chan_active(3); break; case CHR_RPARN: /* ) Channel 4 */ - jump = ((chan_io_status[4] & 0300) == 0200) && - chan_active(4); + jump = chan_active(4); break; case CHR_9: /* 9 Carriage 9 CH1 */ /* 1401 same */ jump = lpr_chan9[1]; @@ -2250,15 +2248,19 @@ sim_instr(void) sim_six_to_ascii[op], ch & 07, (ch & 010)?"": "overlap", sim_six_to_ascii[op_mod], chan_io_status[ch & 07]); - chan_io_status[ch & 07] = IO_CHS_BUSY; + chan_io_status[ch & 07] |= IO_CHS_BUSY; break; case SCPE_NODEV: +fprintf(stderr, "No device %d %d\n\r", ch, temp); + /* Fall through */ case SCPE_IOERR: - chan_io_status[ch & 07] = IO_CHS_NORDY; + chan_io_status[ch & 07] |= IO_CHS_NORDY; break; } - if (CPU_MODEL == 1) + if (CPU_MODEL == 1) { chan_io_status[ch & 07] &= 0177; + chwait = (ch & 07) | 040; + } break; case OP_CC1: @@ -2274,13 +2276,17 @@ sim_instr(void) chan_irq_enb[ch & 7] = 0; break; case SCPE_BUSY: - chan_io_status[ch & 07] = IO_CHS_BUSY; + chan_io_status[ch & 07] |= IO_CHS_BUSY; break; case SCPE_NODEV: case SCPE_IOERR: - chan_io_status[ch & 07] = IO_CHS_NORDY; + chan_io_status[ch & 07] |= IO_CHS_NORDY; break; } + sim_debug(DEBUG_CMD, &cpu_dev, + "%d CC1 on %o %o %s %c %o\n", IAR, ch & 07, temp, + (ch & 010)?"": "overlap", + sim_six_to_ascii[op_mod], chan_io_status[ch & 07]); break; case OP_CC2: @@ -2350,12 +2356,13 @@ sim_instr(void) switch (chan_cmd(temp, t, 0)) { case SCPE_OK: chan_io_status[ch & 07] = 0000; + chan_irq_enb[ch & 7] = 0; if (ch & 010) { chwait = (ch & 07) | 040; } else if (op_mod == CHR_M) { chan_io_status[ch & 07] = IO_CHS_OVER; + chan_irq_enb[ch & 7] = 1; } - chan_irq_enb[ch & 7] = 0; sim_debug(DEBUG_CMD, &cpu_dev, "%d UC on %o %o %s %c %o\n", IAR, ch & 07, temp, (ch & 010)?"": "overlap", @@ -2370,8 +2377,9 @@ sim_instr(void) chan_io_status[ch & 07] = IO_CHS_NORDY; break; } - if (CPU_MODEL == 1) + if (CPU_MODEL == 1) { chan_io_status[ch & 07] &= 0177; + } sim_interval -= 100; break; @@ -2380,12 +2388,19 @@ sim_instr(void) ch = 1; checkchan: chan_proc(); + /* If channel is active, wait for it to finish */ + if (chan_active(ch)) { + chwait = (ch & 07) | 040; + IAR = temp-6; /* Still holds the start of the instruction.*/ + break; + } + if (chan_io_status[ch] & op_mod) { jump = 1; } - chan_io_status[ch] &= 077; - sim_debug(DEBUG_CMD, &cpu_dev, "Check chan %d %o %x\n", ch, - chan_io_status[ch], chan_flags[ch]); + if (pri_enb == 0) { + chan_io_status[ch] &= 077; + } break; case OP_IO2: @@ -2732,6 +2747,7 @@ sim_instr(void) break; case CHR_M: /* M - Floating mul */ + CAR = AAR; temp = oind; oind = 0; reason = do_addsub(0); @@ -2746,16 +2762,18 @@ sim_instr(void) eoind = 1; break; } - CAR = AAR; - DAR = 279; + /* Scan for A word mark */ - qsign = 1; + zind = 1; + ix = 0; + AAR = CAR - 2; ar = ReadP(AAR); DownReg(AAR); + qsign = ((ar & 060) == 040); while (1) { if ((ar & 017) != 10) - qsign = 0; - ClrBit(DAR--, WM); /* Clear word marks */ + zind = 0; + ix++; if (ar & WM || AAR == 0) break; ar = ReadP(AAR); @@ -2763,64 +2781,117 @@ sim_instr(void) sim_interval -= 4; }; - ClrBit(DAR--, WM); /* Extra zero */ - if (qsign) + if (zind) goto zerofacc; + DAR = 279 - ix; + BAR = 297; + + br = ReadP(BAR--); + + /* Compute sign of product */ + qsign ^= ((br & 060) == 040); + qsign = (qsign)?040:060; /* Scan for B word mark */ zind = 1; - br = ReadP(BAR--); + WriteP(DAR--, WM); + temp = DAR; + + /* Copy B over */ while (1) { + WriteP(DAR--, CHR_0 | qsign); + qsign = 0; if ((br & 017) != 10) zind = 0; - WriteP(DAR--, br); if (br & WM || BAR == 279) break; br = ReadP(BAR--); sim_interval -= 2; }; + SetBit(DAR+1, WM); /* If B zero, scan to A word mark and set B zero */ - if (zind || qsign) + if (zind) goto zerofacc; - temp = BAR; /* Save for later */ - BAR = 279; - AAR = CAR; - reason = do_mult(); - if (reason != SCPE_OK) - break; + qsign = ReadP(temp) & 060; + DAR = 297; + br = ReadP(DAR); + BAR = temp = 279; + WriteP(BAR--, CHR_0 | qsign); + for (;ix > 0; ix--) { + WriteP(BAR--, CHR_0); + } + WriteP(BAR--, CHR_0); + zind = 1; + /* Do multiple loop until B word mark */ + while(1) { + uint8 bx; + /* Interloop, multiply one digit */ + ch = bcd_bin[br & 0xf]; + + while (ch != 0) { + WriteP(DAR, bin_bcd[ch - 1] | (br & WM)); + BAR = temp; + bx = ReadP(BAR); + cy = 0; + AAR = CAR-2; + ar = ReadP(AAR); + DownReg(AAR); + while(1) { + ch = bcd_bin[bx & 0xf]; + ch = bcd_bin[ar & 0xf] + ch + cy; + if (ch != 0) /* Clear zero */ + zind = 0; + cy = ch > 9; /* Update carry */ + WriteP(BAR--, bin_bcd[ch] | (bx & 0160)); + bx = ReadP(BAR); + if (ar & WM) + break; + ar = ReadP(AAR); + DownReg(AAR); + sim_interval -= 4; + } + /* Add carry to next digit */ + ch = bcd_bin[bx & 0xf] + cy; + if (ch != 0) /* Clear zero */ + zind = 0; + sim_interval -= 2; + WriteP(BAR--, bin_bcd[ch] | (bx & WM)); + br = ReadP(DAR); + ch = bcd_bin[br & 0xf]; + } + if (br & WM) + break; + temp--; + DAR--; + br = ReadP(DAR); + } /* Count number of leading zeros */ - ix = 0; - BAR++; /* Skip first zero */ + ix = -1; while (BAR != 280) { - br = ReadP(++BAR); + br = ReadP(BAR); if ((br & 017) != 10) break; + BAR++; ix++; } + + /* Find end of result */ + + /* Copy result */ + br = ReadP(BAR++) | WM; + while(DAR != 297) { + WriteP(DAR++, br); + br = ReadP(BAR++); + } + WriteP(DAR, br | qsign); + BAR = 299; if (ix != 0) { - DAR = BAR; - BAR = 299; if(do_addint(-ix)) goto undfacc; - BAR = DAR; } - /* Find end of result */ - CAR = 297; - ar = ReadP(CAR--); - while((ar & WM) == 0) - ar = ReadP(CAR--); - br = (ReadP(BAR) & 017) | WM; - /* Copy result */ - while(CAR != 297 && BAR != 279) { - WriteP(++CAR, br); - br = ReadP(++BAR) & 017; - } - while(CAR != 297) /* Zero fill rest */ - WriteP(++CAR, 10); - SetBit(297, ReadP(279) & 060); /* Copy sign */ break; case CHR_D: /* D - Floating div */ @@ -2857,8 +2928,10 @@ sim_instr(void) }; /* Are fractions same size? */ - if ((br & WM) && (ar & WM) == 0) + if ((br & WM) && (ar & WM) == 0) { + dind = 1; goto zerofacc; + } /* Is A zero? */ if (qsign) { @@ -2912,13 +2985,15 @@ sim_instr(void) goto zerofacc; } + /* Check if exponent went to small */ if (sign) { eoind = 1; break; } - if (ch) + if (ch) { goto undfacc; + } AAR = CAR; /* Do actual divide */ @@ -3096,20 +3171,16 @@ sim_instr(void) urec_irq[2] = 0; break; case CHR_1: /* 1 branch if ch 1 overlap priority */ - if (chan_irq_enb[1]) - jump = (chan_io_status[1] & 0300) == 0300; + jump = (chan_io_status[1] & 0200) == 0200; break; case CHR_2: /* 2 branch if ch 2 overlap priority */ - if (chan_irq_enb[2]) - jump = (chan_io_status[2] & 0300) == 0300; + jump = (chan_io_status[2] & 0200) == 0200; break; case CHR_3: /* 3 branch if ch 3 overlap priority */ - if (chan_irq_enb[3]) - jump = (chan_io_status[3] & 0300) == 0300; + jump = (chan_io_status[3] & 0300) == 0300; break; case CHR_4: /* 4 branch if ch 4 overlap priority */ - if (chan_irq_enb[4]) - jump = (chan_io_status[4] & 0300) == 0300; + jump = (chan_io_status[4] & 0300) == 0300; break; case CHR_Q: /* Q branch if inquiry ch 1 */ jump = inquiry; @@ -3138,12 +3209,12 @@ sim_instr(void) break; case CHR_X: /* X branch and exit */ pri_enb = 0; - sim_debug(DEBUG_PRIO, &cpu_dev, "dis irq\n"); + sim_debug(DEBUG_PRIO, &cpu_dev, "dis irq\n"); jump = 1; break; case CHR_E: /* E branch and enter */ pri_enb = 1; - sim_debug(DEBUG_PRIO, &cpu_dev, "enb irq\n"); + sim_debug(DEBUG_PRIO, &cpu_dev, "enb irq\n"); jump = 1; break; case CHR_A: /* A branch if ch1 attention */ @@ -3182,19 +3253,17 @@ sim_instr(void) "Leave Protect mode %d %d %d\n", AAR & AMASK, prot_enb, reloc); /* If in protect mode, abort */ - if ((prot_enb /*|| reloc*/) /*&& (AAR & BBIT) == 0*/) { - reason = STOP_PROG; + if (prot_enb) { + jump = 1; + prot_enb = 0; + prot_fault |= 2; } else { /* Test protect mode */ - if (reloc && (AAR & BBIT) == 0) { - reason = STOP_PROG; - } else { - jump = 1; - prot_enb = 0; - reloc = 0; - high_addr = -1; - low_addr = -1; - } + jump = 0; + prot_enb = 0; + reloc = 0; + high_addr = -1; + low_addr = -1; } } break; @@ -3218,7 +3287,7 @@ sim_instr(void) if (cpu_unit.flags & OPTION_PROT) { sim_debug(DEBUG_DETAIL, &cpu_dev, "Check prog fault %d %d\n", - AAR, prot_fault&2); + AAR, prot_fault); /* If in protect mode, abort */ if (prot_enb) { reason = STOP_PROG; @@ -3266,29 +3335,24 @@ sim_instr(void) sim_debug(DEBUG_DETAIL, &cpu_dev, "Enable relocation + prot %d\n", AAR & AMASK); - if (prot_enb) { - reason = STOP_PROG; - } else { - prot_enb = 1; - reloc = 1; - prot_fault = 0; - BAR = IAR; - IAR = AAR; - if ((IAR & BBIT) == 0 && low_addr >= 0) { - if (IAR < low_addr) - IAR += 100000 - low_addr; - else - IAR -= low_addr; - } - /* Fix BAR for correct return address */ - if ((BAR & BBIT) == 0 && low_addr >= 0) { - if (BAR < low_addr) - BAR += 100000 - low_addr; - else - BAR -= low_addr; - } - AAR = BAR; + reloc = 1; + prot_fault = 0; + BAR = IAR; + IAR = AAR; + if ((IAR & BBIT) == 0 && low_addr >= 0) { + if (IAR < low_addr) + IAR += 100000 - low_addr; + else + IAR -= low_addr; + } + /* Fix BAR for correct return address */ + if ((BAR & BBIT) == 0 && low_addr >= 0) { + if (BAR < low_addr) + BAR += 100000 - low_addr; + else + BAR -= low_addr; } + AAR = BAR; } break; @@ -3404,6 +3468,7 @@ sim_instr(void) "IAR = %d Prog check AAR=%d BAR=%d low=%d high=%d\n", IAR, AAR, BAR, low_addr, high_addr); prot_fault |= 2; + prot_enb = 0; reason = 0; break; case STOP_PROT: @@ -3411,6 +3476,7 @@ sim_instr(void) "IAR = %d Prot check AAR=%d BAR=%d low=%d high=%d\n", IAR, AAR, BAR, low_addr, high_addr); prot_fault |= 1; + prot_enb = 0; reason = 0; break; default: /* Anything else halt sim */ diff --git a/I7000/i7080_chan.c b/I7000/i7080_chan.c index 531ae7d7b..f94b714d1 100644 --- a/I7000/i7080_chan.c +++ b/I7000/i7080_chan.c @@ -190,7 +190,6 @@ chan_reset(DEVICE * dptr) /* Clear channel assignment */ for (i = 0; i < NUM_CHAN; i++) { - chan_flags[i] = 0; caddr[i] = 0; cmd[i] = 0; bcnt[i] = 0; @@ -361,7 +360,8 @@ int chan_zero_reccnt(int chan) { /* Return next channel data address, advance address by 5 if channel */ uint32 chan_next_addr(int chan) { - int unit = 0; + uint32 unit = 0; + uint32 s_unit = 0; uint32 addr = 0; switch(CHAN_G_TYPE(chan_unit[chan].flags)) { case CHAN_754: @@ -375,8 +375,9 @@ uint32 chan_next_addr(int chan) { unit = 8 + 1024 + chan_unit[chan].u3 * 32; break; } - addr = load_addr(unit); - store_addr(addr + 5, unit); + s_unit = unit; + addr = load_addr(&unit); + store_addr(addr + 5, &s_unit); return addr; } @@ -831,11 +832,19 @@ chan_cmd(uint16 dev, uint16 dcmd, uint32 addr) switch(CHAN_G_TYPE(chan_unit[chan].flags)) { case CHAN_754: case CHAN_UREC: + if (M[caddr[chan]] == CHR_GM) { + return SCPE_OK; + } cmd[chan] |= CHAN_NOREC; break; case CHAN_7621: dcmd &= ~ CHAN_ZERO; switch(dcmd & 0xf) { + case 0: + if (M[caddr[chan]] == CHR_GM) { + return SCPE_OK; + } + break; case 1: cmd[chan] |= CHAN_NOREC; break; case 2: unit = 512 + chan_unit[chan].u3 * 32; @@ -901,6 +910,7 @@ chan_cmd(uint16 dev, uint16 dcmd, uint32 addr) chan_flags[chan] &= ~(CHS_EOF|CHS_ERR|CHS_ATTN); /* Activate channel if select raised */ if (r == SCPE_OK && chan_flags[chan] & DEV_SEL) { + uint32 t_unit; chan_flags[chan] |= STA_ACTIVE; irqdev[chan] = dev; irqflags &= ~(1 << chan); @@ -920,13 +930,17 @@ chan_cmd(uint16 dev, uint16 dcmd, uint32 addr) unit = 512 + chan_unit[chan].u3 * 32; AC[unit+16+5] = 10; /* Set digit next to 0 */ AC[unit+24+5] = 10; - store_addr(caddr[chan], 8 + unit); + sim_debug(DEBUG_DETAIL, &chan_dev, + "chan %d set addr %d\n", chan, caddr[chan]); + t_unit = 8 + unit; + store_addr(caddr[chan], &t_unit); if (cmd[chan] & CHAN_RECCNT && chan_zero_reccnt(chan)) { cmd[chan] &= ~CHAN_RECCNT; } break; case CHAN_7908: - store_addr(caddr[chan], 8+1024 + chan_unit[chan].u3 * 32); + t_unit = 8+1024+chan_unit[chan].u3 * 32; + store_addr(caddr[chan], &t_unit); break; } } diff --git a/I7000/i7080_cpu.c b/I7000/i7080_cpu.c index 69fa0cc5d..fe7fe23e9 100644 --- a/I7000/i7080_cpu.c +++ b/I7000/i7080_cpu.c @@ -74,6 +74,10 @@ #define EMULATE2 (2 << UNIT_EMU) #define UNIT_V_NONSTOP (UNIT_EMU + 2) #define NONSTOP (1 << UNIT_V_NONSTOP) +#define UNIT_V_IOIRQ (UNIT_V_NONSTOP + 1) +#define IOIRQ (1 << UNIT_V_IOIRQ) +#define UNIT_V_40K (UNIT_V_IOIRQ + 1) +#define EMU40K (1 << UNIT_V_40K) #define CPU_702 0x0 #define CPU_705 0x1 @@ -116,8 +120,8 @@ const char *cpu_description (DEVICE *dptr); uint32 read_addr(uint8 *reg, uint8 *zone); void write_addr(uint32 addr, uint8 reg, uint8 zone); -uint32 load_addr(int loc); -void store_addr(uint32 addr, int loc); +uint32 load_addr(uint32 *loc); +void store_addr(uint32 addr, uint32 *loc); void store_cpu(uint32 addr, int full); void load_cpu(uint32 addr, int full); uint16 get_acstart(uint8 reg); @@ -197,7 +201,7 @@ uint8 cmp_order[0100] = { #define SIGN (ASIGN|BSIGN) #define ZERO (AZERO|BZERO) -#define IRQFLAGS (INSTFLAG|MCHCHK|IOCHK|RECCHK|ACOFLAG|SGNFLAG) +#define IRQFLAGS (ANYFLAG) uint8 M[MAXMEMSIZE] = { 0 }; /* memory */ uint32 EMEMSIZE; /* Physical memory size */ @@ -298,6 +302,10 @@ MTAB cpu_mod[] = { {EMULATE3, EMULATE3, "EMU7053", "EMU7053", NULL, NULL, NULL}, {NONSTOP, 0, "PROGRAM", "PROGRAM", NULL, NULL, NULL}, {NONSTOP, NONSTOP, "NONSTOP", "NONSTOP", NULL, NULL, NULL}, + {IOIRQ, 0, "NOIOIRQ", "NOIOIRQ", NULL, NULL, NULL}, + {IOIRQ, IOIRQ, "IOIRQ", "IOIRQ", NULL, NULL, NULL}, + {EMU40K, 0, "NOEMU40K", "NOEMU40K", NULL, NULL, NULL}, + {EMU40K, EMU40K, "EMU40K", "EMU40K", NULL, NULL, NULL}, {MTAB_XTD | MTAB_VDV | MTAB_NMO | MTAB_SHP, 0, "HISTORY", "HISTORY", &cpu_set_hist, &cpu_show_hist}, {0} @@ -318,7 +326,7 @@ uint16 prev_addr[6 * 256]; /* Previous storage location */ uint16 next_half[6 * 256]; /* Forward half loop locations */ /*#define ReadP(addr) M[(addr) % EMEMSIZE] */ -#define WriteP(addr, data) M[(addr) % EMEMSIZE] = data +/*#define WriteP(addr, data) M[(addr) % EMEMSIZE] = data */ #define Next(reg) if (reg == 0) reg = EMEMSIZE; reg-- #define Prev5(reg) reg += 5; if (reg > EMEMSIZE) reg -= EMEMSIZE @@ -328,7 +336,11 @@ uint16 next_half[6 * 256]; /* Forward half loop locations */ /* Read 1 character from memory, checking for reducancy error. */ uint8 ReadP(uint32 addr, uint16 flag) { uint8 value; - value = M[(addr) % EMEMSIZE]; + addr %= EMEMSIZE; + if ((flags & EMU40K) != 0) { + addr %= 40000; + } + value = M[addr]; if (value & 0100) { if (flag == 0) return value; @@ -336,7 +348,7 @@ uint8 ReadP(uint32 addr, uint16 flag) { } else if (value == 0) { flags |= flag|ANYFLAG; } - return value & 077; + return value; } /* Read 5 characters from memory starting at addr */ @@ -351,6 +363,15 @@ uint32 Read5(uint32 addr, uint16 flag) { return value; } +/* Write 1 character to memory. */ +void WriteP(uint32 addr, uint8 value) { + addr %= EMEMSIZE; + if ((flags & EMU40K) != 0) { + addr %= 40000; + } + M[addr] = value; +} + /* Write 5 characters from memory starting at addr */ void Write5(uint32 addr, uint32 value) { WriteP(addr-4, 077 & (value >> (4 * 6))); @@ -453,11 +474,6 @@ sim_instr(void) if ((cpu_unit.flags & NONSTOP) && (intprog == 0) && intmode != 0 && selreg2 == 0 && (IRQFLAGS & flags)) { /* Process as interrupt */ - Next(IC); /* Back up to start of instruction */ - Next(IC); - Next(IC); - Next(IC); - Next(IC); store_cpu(0x3E0, 1); load_cpu(0x2A0, 0); intprog = 1; @@ -495,41 +511,8 @@ sim_instr(void) flags &= ~(SGNFLAG|ANYFLAG); break; } - } else if (cpu_unit.flags & NONSTOP && intprog && (IRQFLAGS & flags)) { - /* Issue sim halt */ - if (flags & INSTFLAG) { - reason = STOP_UUO; - flags &= ~ (INSTFLAG|ANYFLAG); - break; - } - if (flags & MCHCHK) { - reason = STOP_MMTRP; - flags &= ~(MCHCHK|ANYFLAG); - break; - } - if (flags & IOCHK) { - reason = STOP_IOCHECK; - flags &= ~(IOCHK|ANYFLAG); - break; - } - if (flags & RECCHK) { - reason = STOP_RECCHK; - flags &= ~(RECCHK|ANYFLAG); - break; - } - if (flags & ACOFLAG) { - reason = STOP_ACOFL; - flags &= ~(ACOFLAG|ANYFLAG); - break; - } - if (flags & SGNFLAG) { - reason = STOP_SIGN; - flags &= ~(SGNFLAG|ANYFLAG); - break; - } } - /* If we are waiting on I/O, don't fetch */ if (!chwait) { if (!iowait) { @@ -763,6 +746,12 @@ sim_instr(void) default: break; } + if (CPU_MODEL == CPU_7080 && + (cpu_unit.flags & IOIRQ) != 0 && reg < 4 && + (flags & EIGHTMODE) == 0) { + flags |= INSTFLAG|ANYFLAG; + t = 0; + } } else { switch((selreg >> 8) & 0xff) { case 20: /* Tape DS */ @@ -824,6 +813,15 @@ sim_instr(void) default: /* Drum */ break; } + if (CPU_MODEL == CPU_7080 && + (cpu_unit.flags & IOIRQ) != 0 && + (flags & EIGHTMODE) == 0) { + temp = (selreg >> 8) & 0xff; + if (temp != 9 && temp != 5) { + flags |= INSTFLAG|ANYFLAG; + t = 0; + } + } } if (t) { IC = MAC; @@ -962,8 +960,10 @@ sim_instr(void) cr2 &= 060; cr2 |= 012; } - if ((cr2 & 060) == 040 || (cr2 & 060) == 020) + if ((cr2 & 060) == 040 || (cr2 & 060) == 020) { cr2 |= 0100; + flags |= MCHCHK|ANYFLAG; + } } WriteP(MA, cr2); Next(MA); @@ -1045,6 +1045,9 @@ sim_instr(void) AC[addr] = 10; } else if (AC[addr] != 10) flags &= ~(ZERO & fmsk); /* No zero, adjust flag */ + if (AC[addr] & 0100) { + flags |= MCHCHK|ANYFLAG; + } MAC--; addr = next_addr[addr]; sim_interval --; /* count down */ @@ -1405,6 +1408,12 @@ sim_instr(void) chan_chr_13(); memset(ioflags, 0, sizeof(ioflags)); flags &= ~(IRQFLAGS); + if (CPU_MODEL == CPU_7080 && + (cpu_unit.flags & IOIRQ) != 0 && + (flags & EIGHTMODE) == 0 && + ((selreg >> 8) & 0xff) != 5) { + flags |= ANYFLAG|INSTFLAG; + } break; case 14: /* EEM */ @@ -1521,6 +1530,12 @@ sim_instr(void) break; } } + if (iowait == 0 && CPU_MODEL == CPU_7080 && + (cpu_unit.flags & IOIRQ) != 0 && + (flags & EIGHTMODE) == 0 && + ((selreg >> 8) & 0xff) != 5) { + flags |= ANYFLAG|INSTFLAG; + } break; case OP_RD: /* READ */ @@ -1538,6 +1553,12 @@ sim_instr(void) flags |= ANYFLAG|INSTFLAG; break; } + if (iowait == 0 && CPU_MODEL == CPU_7080 && + (cpu_unit.flags & IOIRQ) != 0 && + (flags & EIGHTMODE) == 0 && + ((selreg >> 8) & 0xff) != 5) { + flags |= ANYFLAG|INSTFLAG; + } break; case OP_WR: /* WRITE */ @@ -1555,6 +1576,12 @@ sim_instr(void) flags |= ANYFLAG|INSTFLAG; break; } + if (iowait == 0 && CPU_MODEL == CPU_7080 && + (cpu_unit.flags & IOIRQ) != 0 && + (flags & EIGHTMODE) == 0 && + ((selreg >> 8) & 0xff) != 5) { + flags |= ANYFLAG|INSTFLAG; + } break; case OP_WRE: /* WR ER */ @@ -1572,11 +1599,25 @@ sim_instr(void) flags |= ANYFLAG|INSTFLAG; break; } + if (iowait == 0 && CPU_MODEL == CPU_7080 && + (cpu_unit.flags & IOIRQ) != 0 && + (flags & EIGHTMODE) == 0 && + ((selreg >> 8) & 0xff) != 5) { + flags |= ANYFLAG|INSTFLAG; + } break; case OP_RWW: /* RWW 705 only */ MAC2 = MAC; - selreg2 = selreg | 0x8000; + if (CPU_MODEL == CPU_7080 && + (cpu_unit.flags & IOIRQ) != 0 && + (flags & EIGHTMODE) == 0 && + ((selreg >> 8) & 0xff) != 5) { + flags |= ANYFLAG|INSTFLAG; + selreg2 = selreg; + } else { + selreg2 = selreg | 0x8000; + } break; /* 7080 opcodes */ @@ -1786,7 +1827,7 @@ sim_instr(void) case 14: /* SMT */ write_addr(MAC2, 0, 0); WriteP(MA, 10); /* Finish with zero */ - store_addr(MAC2, addr); + store_addr(MAC2, &addr); sim_interval -= 10; break; } @@ -2186,8 +2227,6 @@ sim_instr(void) break; } t = ReadP(MA, 0); - if (t & 0100) - flags |= MCHCHK|ANYFLAG; sim_interval --; /* count down */ switch(reg) { case 0: /* Nop */ @@ -2198,12 +2237,20 @@ sim_instr(void) case 4: /* 8 */ case 5: /* A */ case 6: /* B */ + if (t & 0100) + flags |= MCHCHK|ANYFLAG; t &= ~(1<<(reg-1)); + t &= 077; break; case 7: /* Reverse A */ + if (t & 0100) + flags |= MCHCHK|ANYFLAG; t ^= 020; + t &= 077; break; case 8: /* Reverse C */ + if (t & 0100) + flags |= MCHCHK; t = M[MA % EMEMSIZE] ^ 0100; break; case 9: /* 1 */ @@ -2212,7 +2259,10 @@ sim_instr(void) case 12: /* 8 */ case 13: /* A */ case 14: /* B */ + if (t & 0100) + flags |= MCHCHK|ANYFLAG; t |= 1<<(reg-9); + t &= 077; break; } WriteP(MA, t); @@ -2224,7 +2274,7 @@ sim_instr(void) } if (hst_lnt) { /* history enabled? */ hst[hst_p].flags = flags; - addr = get_acstart(reg); + addr = spc; for (t = 0; t < 254; t++) { hst[hst_p].store[t] = AC[addr]; addr = next_addr[addr]; @@ -2356,7 +2406,7 @@ void write_addr(uint32 addr, uint8 reg, uint8 zone) { } /* Store converted address in storage */ -void store_addr(uint32 addr, int loc) { +void store_addr(uint32 addr, uint32 *loc) { uint8 value[4]; int i; @@ -2386,7 +2436,7 @@ void store_addr(uint32 addr, int loc) { if ((cpu_unit.flags & EMULATE2)) value[3] |= (addr & 0xc) << 2; else /* 20k */ - value[3] |= (addr & 0x8) << 2; + value[3] |= (addr & 0xc) << 2; break; case CPU_702: /* 702 */ break; @@ -2398,32 +2448,37 @@ void store_addr(uint32 addr, int loc) { value[i] &= 0360; if (value[i] == 0) value[i] = 10; - AC[loc] = value[i]; - loc = next_addr[loc]; + AC[*loc] = value[i]; + *loc = next_addr[*loc]; } } /* Read address from storage */ -uint32 load_addr(int loc) { +uint32 load_addr(uint32 *loc) { uint8 t; + uint8 f; uint8 zone; uint32 addr; - t = AC[loc]; /* First digit */ - loc = next_addr[loc]; + t = AC[*loc]; /* First digit */ + f = t; zone = (t & 060) >> 2; addr = bcd_bin[t & 0xf]; - t = AC[loc]; /* Second digit */ - loc = next_addr[loc]; + *loc = next_addr[*loc]; + t = AC[*loc]; /* Second digit */ + f |= t; addr += dig2[bcd_bin[t & 0xf]]; - t = AC[loc]; /* Read third digit */ - loc = next_addr[loc]; + *loc = next_addr[*loc]; + t = AC[*loc]; /* Read third digit */ + f |= t; addr += dig3[bcd_bin[t & 0xf]]; - t = AC[loc]; /* Save High order address */ - loc = next_addr[loc]; + *loc = next_addr[*loc]; + t = AC[*loc]; /* Save High order address */ + f |= t; zone |= (t & 060) >> 4; addr += dig4[bcd_bin[t & 0xf]]; + *loc = next_addr[*loc]; switch (cpu_type) { case CPU_7080: /* 7080 */ break; @@ -2432,50 +2487,65 @@ uint32 load_addr(int loc) { if (cpu_unit.flags & EMULATE2) zone &= 3; /* 40k */ else - zone &= 013; /* 80k */ + zone &= 7; /* 80k */ break; case CPU_705: /* 705 */ if (cpu_unit.flags & EMULATE2) zone &= 3; /* 40K */ else - zone &= 1; /* 20k */ + zone &= 3; /* 20k */ break; case CPU_702: /* 702 */ zone = 0; /* 10k Memory */ break; } addr += dig_zone[zone]; + /* Set Machine Check if got redundant data */ + if (f & 0100) { + flags |= MCHCHK|ANYFLAG; + } return addr; } /* Store converted hex address in storage */ -void store_hex(uint32 addr, int loc) { +void store_hex(uint32 addr, uint32 *loc) { /* Convert address into BCD first */ - AC[loc] = bin_bcd[addr & 0xf]; - loc = next_addr[loc]; - AC[loc] = bin_bcd[(addr >> 4) & 0xf]; - loc = next_addr[loc]; - AC[loc] = bin_bcd[(addr >> 8) & 0xf]; - loc = next_addr[loc]; - AC[loc] = bin_bcd[(addr >> 12) & 0xf]; + AC[*loc] = bin_bcd[addr & 0xf]; + *loc = next_addr[*loc]; + AC[*loc] = bin_bcd[(addr >> 4) & 0xf]; + *loc = next_addr[*loc]; + AC[*loc] = bin_bcd[(addr >> 8) & 0xf]; + *loc = next_addr[*loc]; + AC[*loc] = bin_bcd[(addr >> 12) & 0xf]; + *loc = next_addr[*loc]; } /* Read hex address from storage */ -uint32 load_hex(int loc) { +uint32 load_hex(uint32 *loc) { uint8 t; + uint8 f; uint32 addr; - t = AC[loc]; /* First digit */ + t = AC[*loc]; /* First digit */ + f = t; addr = bcd_bin[t & 0xf]; - loc = next_addr[loc]; - t = AC[loc]; /* Second digit */ + *loc = next_addr[*loc]; + t = AC[*loc]; /* Second digit */ + f |= t; addr += bcd_bin[t & 0xf] << 4; - loc = next_addr[loc]; - t = AC[loc]; /* Read third digit */ + *loc = next_addr[*loc]; + t = AC[*loc]; /* Read third digit */ + f |= t; addr += bcd_bin[t & 0xf] << 8; - loc = next_addr[loc]; - t = AC[loc]; /* Save High order address */ + *loc = next_addr[*loc]; + t = AC[*loc]; /* Save High order address */ + f |= t; addr += bcd_bin[t & 0xf] << 12; + *loc = next_addr[*loc]; + /* Set Machine Check if got redundant data */ + if (f & 0100) { + flags |= MCHCHK|ANYFLAG; + } return addr; } @@ -2497,89 +2567,137 @@ uint16 get_acstart(uint8 reg) { /* Store CPU state in CASU 15 */ void store_cpu(uint32 addr, int full) { - uint8 t; + uint8 t; - store_addr(IC, addr); - addr = next_addr[addr]; - addr = next_addr[addr]; - addr = next_addr[addr]; - addr = next_addr[addr]; + store_addr(IC, &addr); /* Save status characters */ - t = flags & 0xf; - AC[addr] = 040 | ((t + 8) & 027); - addr = next_addr[addr]; - t = (flags >> 4) & 0xf; - AC[addr] = 040 | ((t + 8) & 027); - addr = next_addr[addr]; - t = (flags >> 8) & 0xf; - AC[addr] = 040 | ((t + 8) & 027); - addr = next_addr[addr]; - t = (flags >> 12) & 0x3; - AC[addr] = 040 | t; - if (full) { - addr = next_addr[addr]; - AC[addr] = bin_bcd[spc & 7]; - addr = next_addr[addr]; - AC[addr] = bin_bcd[(spc >> 3) & 3]; - addr = next_addr[addr]; - AC[addr] = bin_bcd[(spc >> 5) & 7]; - addr = next_addr[addr]; - AC[addr] = bin_bcd[(spc >> 8) & 7]; - addr = next_addr[addr]; - for(; addr < 0x3F8; addr++) - AC[addr] = 10; - for(; addr < 0x400; addr++) - AC[addr] = 0; - store_addr(MAC2, 0x3F0); - store_hex(selreg, 0x3F8); - } + t = flags & 0xf; + AC[addr] = 040 | ((t + 8) & 027); + addr = next_addr[addr]; + t = (flags >> 4) & 0xf; + AC[addr] = 040 | ((t + 8) & 027); + addr = next_addr[addr]; + t = (flags >> 8) & 0xf; + AC[addr] = 040 | ((t + 8) & 027); + addr = next_addr[addr]; + t = (flags >> 12) & 0x3; + AC[addr] = 040 | t; + if (full) { + addr = next_addr[addr]; + AC[addr] = bin_bcd[spc & 7]; + addr = next_addr[addr]; + AC[addr] = bin_bcd[(spc >> 3) & 3]; + addr = next_addr[addr]; + AC[addr] = bin_bcd[(spc >> 5) & 7]; + addr = next_addr[addr]; + AC[addr] = bin_bcd[(spc >> 8) & 7]; + addr = next_addr[addr]; + AC[addr] = 10; + addr = next_addr[addr]; + AC[addr] = 10; + addr = next_addr[addr]; + AC[addr] = 10; + addr = next_addr[addr]; + AC[addr] = 10; + addr = next_addr[addr]; + store_addr(MAC2, &addr); + AC[addr] = 10; + addr = next_addr[addr]; + AC[addr] = 10; + addr = next_addr[addr]; + AC[addr] = 10; + addr = next_addr[addr]; + AC[addr] = 10; + addr = next_addr[addr]; + store_hex(selreg, &addr); + AC[addr] = 0; + addr = next_addr[addr]; + AC[addr] = 0; + addr = next_addr[addr]; + AC[addr] = 0; + addr = next_addr[addr]; + AC[addr] = 0; + } } /* Load CPU State from storage */ void load_cpu(uint32 addr, int full) { uint8 t; + uint8 f; - IC = load_addr(addr); - addr = next_addr[addr]; - addr = next_addr[addr]; - addr = next_addr[addr]; - addr = next_addr[addr]; flags = 0; - t = AC[addr++]; + IC = load_addr(&addr); + t = AC[addr]; + addr = next_addr[addr]; + f = t; flags |= (t & 0x7) | ((t >> 1) & 0x8); - t = AC[addr++]; + t = AC[addr]; + addr = next_addr[addr]; + f |= t; flags |= ((t & 0x7) | ((t >> 1) & 0x8)) << 4; - t = AC[addr++]; + t = AC[addr]; + addr = next_addr[addr]; + f |= t; flags |= ((t & 0x7) | ((t >> 1) & 0x8)) << 8; - t = AC[addr++]; + t = AC[addr]; + addr = next_addr[addr]; + f |= t; flags |= (t & 0x3) << 12; - /* Adjust Max memory if mode changed */ - EMEMSIZE = MEMSIZE; - if (flags & EIGHTMODE) { - cpu_type = CPU_7080; - } else { - cpu_type = (cpu_unit.flags & EMULATE3)? CPU_7053:CPU_705; - EMEMSIZE = MEMSIZE; - if (cpu_unit.flags & EMULATE2 && EMEMSIZE > 40000) - EMEMSIZE = 40000; - if (cpu_type == CPU_705 && (cpu_unit.flags & EMULATE2) == 0 - && EMEMSIZE > 20000) - EMEMSIZE = 20000; - if (EMEMSIZE > 80000) - EMEMSIZE = 80000; + /* Update emulation mode */ + if (CPU_MODEL == CPU_7080) { + if (flags & EIGHTMODE) { + EMEMSIZE = MEMSIZE; + cpu_type = CPU_7080; + } else { + cpu_type = (cpu_unit.flags & EMULATE3)? CPU_7053:CPU_705; + EMEMSIZE = MEMSIZE; + if (cpu_unit.flags & EMULATE2 && EMEMSIZE > 40000) + EMEMSIZE = 40000; + if (cpu_type == CPU_705 && (cpu_unit.flags & EMULATE2) == 0 && + EMEMSIZE > 20000) + EMEMSIZE = 20000; + if (EMEMSIZE > 80000) + EMEMSIZE = 80000; + } } if (full) { - spc = bcd_bin[AC[addr++]] & 07; /* Units digit */ + int i; + t = AC[addr]; + addr = next_addr[addr]; + f |= t; + spc = bcd_bin[t & 0xf] & 07; /* Units digit */ /* One of words */ - spc += (bcd_bin[AC[addr++]] & 3) << 3; /* Tens digit */ + t = AC[addr]; + addr = next_addr[addr]; + f |= t; + spc += (bcd_bin[t & 0xf] & 3) << 3; /* Tens digit */ /* One of four word sets */ - spc += (bcd_bin[AC[addr++]] & 7) << 5; /* Hundreds */ + t = AC[addr]; + addr = next_addr[addr]; + f |= t; + spc += (bcd_bin[t & 0xf] & 7) << 5; /* Hundreds */ /* Bank */ - spc += (bcd_bin[AC[addr++]] & 7) << 8; /* Thousands */ - addr += 4; - MAC2 = load_addr(addr); - addr += 8; - selreg = load_hex(addr); + t = AC[addr]; + addr = next_addr[addr]; + f |= t; + spc += (bcd_bin[t & 0xf] & 7) << 8; /* Thousands */ + for (i = 0; i < 4; i++) { + f |= AC[addr]; + addr = next_addr[addr]; + } + MAC2 = load_addr(&addr); + for (i = 0; i < 4; i++) { + f |= AC[addr]; + addr = next_addr[addr]; + } + selreg = load_hex(&addr); + for (i = 0; i < 4; i++) { + f |= AC[addr]; + addr = next_addr[addr]; + } + } + if (f & 0100) { + flags |= MCHCHK | ANYFLAG; } } @@ -2825,6 +2943,7 @@ do_divide(int reg, uint16 fmsk) int remtrig; int carry; int dzt; + int over; /* Step I, put storage mark before start of AC */ at = 0; @@ -2833,6 +2952,7 @@ do_divide(int reg, uint16 fmsk) smt = 1; carry = 0; msign = 0; + over = 0; /* Step II, step address until we find storage mark */ step2: @@ -2947,6 +3067,8 @@ do_divide(int reg, uint16 fmsk) tsac = tspc; if (t >= 10) { flags |= ACOFLAG|ANYFLAG; + msign = 0; + over = 1; at = 1; goto step2; } @@ -2967,6 +3089,8 @@ do_divide(int reg, uint16 fmsk) at = 1; if (t >= 10) { flags |= ACOFLAG|ANYFLAG; + msign = 0; + over = 1; goto step2; } dzt = 0; @@ -3065,7 +3189,9 @@ do_divide(int reg, uint16 fmsk) /* Update sign and zero */ flags ^= msign; - flags &= ~(((flags & ZERO) >> 2) & fmsk); + if (over == 0) { + flags &= ~(((flags & ZERO) >> 2) & fmsk); + } return SCPE_OK; } @@ -3380,8 +3506,12 @@ cpu_show_hist(FILE * st, UNIT * uptr, int32 val, CONST void *desc) (h->flags & LOWFLAG)? 'l' : ((h->flags & HIGHFLAG) ? 'h' : 'e')); - for(len--; len >= 0; len--) + for(len--; len >= 0; len--) { fputc(mem_to_ascii[h->store[len] & 077], st); + if (h->store[len] & 0100) { + fputc('|', st); + } + } fputc('@', st); if (h->flags & 0x7f0) { int i; diff --git a/I7000/i7080_defs.h b/I7000/i7080_defs.h index ea91ead04..81701310e 100644 --- a/I7000/i7080_defs.h +++ b/I7000/i7080_defs.h @@ -36,8 +36,8 @@ int chan_cmd(uint16 dev, uint16 cmd, uint32 addr); int chan_mapdev(uint16 dev); /* Process the CHR 3 13 command and abort all channel activity */ void chan_chr_13(); -uint32 load_addr(int loc); -void store_addr(uint32 addr, int loc); +uint32 load_addr(uint32 *loc); +void store_addr(uint32 addr, uint32 *loc); /* Opcode definitions. */ #define OP_TR CHR_1 diff --git a/I7000/i7090_cdr.c b/I7000/i7090_cdr.c index a72f15067..e075646c1 100644 --- a/I7000/i7090_cdr.c +++ b/I7000/i7090_cdr.c @@ -109,8 +109,12 @@ uint32 cdr_cmd(UNIT * uptr, uint16 cmd, uint16 dev) } return SCPE_BUSY; } - chan_set_attn(chan); - return SCPE_NODEV; + uptr->wait = 0; + uptr->u5 |= URCSTA_READ | URCSTA_CMD | (24 << CDRPOSSHIFT); + chan_set_sel(chan, 0); + chan_clear_status(chan); + sim_activate(uptr, us_to_ticks(1000)); /* activate */ + return SCPE_OK; } t_stat cdr_srv(UNIT * uptr) diff --git a/I7000/i7090_chan.c b/I7000/i7090_chan.c index c2ef53cd2..8d9639f06 100644 --- a/I7000/i7090_chan.c +++ b/I7000/i7090_chan.c @@ -376,11 +376,10 @@ chan_proc() if ((chan_flags[chan] & DEV_SEL) == 0 && (chan_flags[chan] & STA_TWAIT)) { if (chan_dev.dctrl & cmask) - sim_debug(DEBUG_TRAP, &chan_dev, "chan %d Trap\n", - chan); + sim_debug(DEBUG_TRAP, &chan_dev, "chan %d Trap IC=%06o\n", + chan, IC); iotraps |= 1 << chan; - chan_flags[chan] &= - ~(STA_START | STA_ACTIVE | STA_WAIT | STA_TWAIT); + chan_flags[chan] &= ~(STA_START | STA_ACTIVE | STA_WAIT | STA_TWAIT); chan_info[chan] = 0; continue; } @@ -441,7 +440,7 @@ chan_proc() /* Device has given us a dataword */ case DEV_FULL: /* If we are not waiting EOR save it in memory */ - if ((cmd[chan] & 1) == 0) { + if (/*(chan_flags[chan] & CHS_ERR) == 0 &&*/ (cmd[chan] & 1) == 0) { if (chan_dev.dctrl & cmask) sim_debug(DEBUG_DATA, &chan_dev, "chan %d data < %012llo\n", chan, assembly[chan]); @@ -1569,6 +1568,7 @@ chan_write_char(int chan, uint8 * data, int flags) } else { int cnt = --bcnt[chan]; t_uint64 wd; + if (CHAN_G_TYPE(chan_unit[chan].flags) == CHAN_PIO) wd = MQ; else diff --git a/I7000/i7090_cpu.c b/I7000/i7090_cpu.c index ca71b5f7c..669d15894 100644 --- a/I7000/i7090_cpu.c +++ b/I7000/i7090_cpu.c @@ -815,6 +815,8 @@ sim_instr(void) MA = 012; f = 0; + sim_debug(DEBUG_TRAP, &cpu_dev, + "Checking trap chan IC=%06o %06o\n", IC, iotraps); for (shiftcnt = 1; shiftcnt < NUM_CHAN; shiftcnt++) { /* CRC *//* Trap *//* EOF */ /* Wait until channel stops to trigger interupts */ @@ -828,10 +830,12 @@ sim_instr(void) iotraps &= ~(1 << shiftcnt); } } - if (mask & DMASK & ioflags && chan_stat(shiftcnt, CHS_ERR)) + if (mask & DMASK & ioflags && chan_stat(shiftcnt, CHS_ERR)) { f |= 2; /* We have device error */ + } /* check if we need to perform a trap */ if (f) { +// iotraps &= ~(1 << (shiftcnt + 18)); /* HTR/HPR behave like wait if protected */ if (hltinst) temp = (((t_uint64) bcore & 3) << 31) | @@ -854,8 +858,8 @@ sim_instr(void) sim_interval = sim_interval - 1; /* count down */ SR = ReadP(MA); sim_debug(DEBUG_TRAP, &cpu_dev, - "Doing trap chan %c %o >%012llo loc %o %012llo IC=%06o\n", - shiftcnt + 'A' - 1, f, temp, MA, SR, IC); + "Doing trap chan %c %o >%012llo loc %o %012llo IC=%06o %06o\n", + shiftcnt + 'A' - 1, f, temp, MA, SR, IC, iotraps); if (hst_lnt) { /* history enabled? */ hst_p = (hst_p + 1); /* next entry */ if (hst_p >= hst_lnt) @@ -1329,10 +1333,12 @@ sim_instr(void) if ((bcore & 4) || STM) goto seltrap; itrap = 1; +// iotraps &= ~(AMASK & (ioflags << 1)); if (CPU_MODEL == CPU_709) ihold = 1; else ihold = 2; + sim_debug(DEBUG_TRAP, &cpu_dev, "rxt %06o\n", iotraps); } break; case OP_LMTM: @@ -1481,7 +1487,7 @@ sim_instr(void) hltinst = 1; ihold = 0; /* Kill any hold on traps now */ if (opcode == OP_HTR) { - fptemp = IC-1; + fptemp = IC; IC = MA; } else fptemp = IC; @@ -3339,14 +3345,16 @@ sim_instr(void) itrap = 1; else itrap = 0; - sim_debug(DEBUG_TRAP, &cpu_dev, "ENB %012llo\n", ioflags); - ihold = 1; + sim_debug(DEBUG_TRAP, &cpu_dev, "ENB %012llo %06o\n", ioflags, iotraps); /* * IBSYS can't have an trap right after ENB or it will hang * on a TTR * in IBNUC. */ - if (CPU_MODEL >= CPU_7090) + if (CPU_MODEL >= CPU_7090) { + ihold = 1; break; + } +#if 0 temp = 00000001000001LL; for (shiftcnt = 1; shiftcnt < NUM_CHAN; shiftcnt++) { @@ -3360,6 +3368,7 @@ sim_instr(void) ihold = 0; temp <<= 1; } +#endif break; #endif @@ -3393,15 +3402,21 @@ sim_instr(void) switch (chan_cmd(MA, opcode)) { case SCPE_BUSY: iowait = 1; /* Channel is active, hold */ + ihold = 1; /* Hold interupts for one cycle */ break; case SCPE_OK: - if (((MA >> 9) & 017) == 0) { - if (opcode==IO_RDS) - MQ = 0; - chan_clear(0, CHS_EOF|CHS_EOT|DEV_REOR); + { uint16 temp16; + temp16 = (MA >> 9) & 017; + if (temp16 == 0) { + if (opcode==IO_RDS) + MQ = 0; + chan_clear(0, CHS_EOF|CHS_EOT|DEV_REOR); + } else { + iotraps &= ~(1 << temp16); + chan_clear(temp16, CHS_EOF|CHS_EOT|DEV_REOR); + } } ihold = 1; /* Hold interupts for one cycle */ - iotraps &= ~(1 << ((MA >> 9) & 017)); break; case SCPE_IOERR: iocheck = 1; @@ -4183,7 +4198,7 @@ cpu_reset(DEVICE * dptr) interval_irq = dcheck = acoflag = mqoflag = iocheck = 0; sim_brk_types = sim_brk_dflt = SWMASK('E'); limitaddr = 077777; - memmask = MEMMASK; + memmask = MEMSIZE-1; if (cpu_unit.flags & OPTION_TIMER) { sim_rtcn_init_unit (&cpu_unit, cpu_unit.wait, TMR_RTC); sim_activate(&cpu_unit, cpu_unit.wait);