diff --git a/SEL32/sel32_chan.c b/SEL32/sel32_chan.c index 8b03c1b..7f341cf 100644 --- a/SEL32/sel32_chan.c +++ b/SEL32/sel32_chan.c @@ -159,15 +159,12 @@ int32 FIFO_Put(uint16 chsa, uint32 entry) dibp->chan_fifo_in += 1; /* next entry */ dibp->chan_fifo_in %= FIFO_SIZE; /* modulo FIFO size */ num = (dibp->chan_fifo_in - dibp->chan_fifo_out + FIFO_SIZE) % FIFO_SIZE; -// sim_debug(DEBUG_EXP, &cpu_dev, -// "FIFO_Put FIFO put entry %04x for chsa %04x count %02x\n", entry, chsa, num); return SCPE_OK; /* all OK */ } /* get the next entry from the FIFO */ int32 FIFO_Get(uint16 chsa, uint32 *old) { -// int32 num; /* number of entries */ DIB *dibp = dib_chan[get_chan(chsa)]; /* get DIB pointer for channel */ if (dibp == NULL) { sim_debug(DEBUG_EXP, &cpu_dev, @@ -182,9 +179,6 @@ int32 FIFO_Get(uint16 chsa, uint32 *old) *old = dibp->chan_fifo[dibp->chan_fifo_out]; /* get the next entry */ dibp->chan_fifo_out += 1; /* next entry */ dibp->chan_fifo_out %= FIFO_SIZE; /* modulo FIFO size */ -// num = (dibp->chan_fifo_in - dibp->chan_fifo_out + FIFO_SIZE) % FIFO_SIZE; -// sim_debug(DEBUG_EXP, &cpu_dev, -// "FIFO_Get FIFO get entry %04x for chsa %04x leaving count %02x\n", *old, chsa, num); return SCPE_OK; /* all OK */ } @@ -206,23 +200,19 @@ int32 FIFO_Num(uint16 chsa) /* add an entry to the RDYQ */ int32 RDYQ_Put(uint32 entry) { -// int32 num; /* number of entries */ + int32 num; /* number of entries */ /* see if RDYQ FIFO is full */ if (RDYQIN == ((RDYQOUT-1+RDYQ_SIZE) % RDYQ_SIZE)) { -// num = (RDYQIN - RDYQOUT + RDYQ_SIZE) % RDYQ_SIZE; /* number of entries */ -// sim_debug(DEBUG_XIO, &cpu_dev, "RDYQ_Put queue FULL count %02x\n", num); + num = (RDYQIN - RDYQOUT + RDYQ_SIZE) % RDYQ_SIZE; /* number of entries */ + sim_debug(DEBUG_EXP, &cpu_dev, "RDYQ_Put queue FULL count %02x\n", num); return -1; /* RDYQ Full */ } RDYQ[RDYQIN] = entry; /* add new entry */ RDYQIN += 1; /* next entry */ RDYQIN %= RDYQ_SIZE; /* modulo RDYQ size */ -// num = (RDYQIN - RDYQOUT + RDYQ_SIZE) % RDYQ_SIZE; /* number of entries */ -// sim_debug(DEBUG_XIO, &cpu_dev, "RDYQ_Put entry %04x count %02x\n", entry, num); irq_pend = 1; /* do a scan */ //XXwaitrdyq = 10; /* UTX21A installs with this, but diags hang */ -//ZZwaitrdyq = 8; -//XXwaitrdyq = 5; -// waitrdyq = 2; +//XXwaitrdyq = 2; waitrdyq = 1; /* wait at least 1 instruction */ return SCPE_OK; /* all OK */ } @@ -230,7 +220,6 @@ int32 RDYQ_Put(uint32 entry) /* get the next entry from the RDYQ */ int32 RDYQ_Get(uint32 *old) { -// int32 num; /* number of entries */ /* see if the RDYQ is empty */ if (RDYQIN == RDYQOUT) { return -1; /* RDYQ is empty, tell caller */ @@ -238,8 +227,6 @@ int32 RDYQ_Get(uint32 *old) *old = RDYQ[RDYQOUT]; /* get the next entry */ RDYQOUT += 1; /* next entry */ RDYQOUT %= RDYQ_SIZE; /* modulo RDYQ size */ -// num = (RDYQIN - RDYQOUT + RDYQ_SIZE) % RDYQ_SIZE; /* number of entries */ -// sim_debug(DEBUG_XIO, &cpu_dev, "RDYQ_Get entry %04x leaving %02x\n", *old, num); return SCPE_OK; /* all OK */ } @@ -248,8 +235,6 @@ int32 RDYQ_Num(void) { /* calc entries */ int32 num = (RDYQIN - RDYQOUT + RDYQ_SIZE) % RDYQ_SIZE; /* number of entries */ -// sim_debug(DEBUG_XIO, &cpu_dev, "RDYQ_Num entres %04x\n", num); -// return ((RDYQIN - RDYQOUT + RDYQ_SIZE) % RDYQ_SIZE); return num; } @@ -271,14 +256,12 @@ int32 IOCLQ_Put(IOCLQ *qptr, uint32 entry) qptr->ioclq_in += 1; /* next entry */ qptr->ioclq_in %= IOCLQ_SIZE; /* modulo IOCLQ size */ num = (qptr->ioclq_in - qptr->ioclq_out + IOCLQ_SIZE) % IOCLQ_SIZE; -// sim_debug(DEBUG_XIO, &cpu_dev, "IOCLQ_Put entry %06x count %02x\n", entry, num); return SCPE_OK; /* all OK */ } /* get the next entry from the IOCLQ */ int32 IOCLQ_Get(IOCLQ *qptr, uint32 *old) { -// int32 num; /* number of entries */ if (qptr == NULL) { sim_debug(DEBUG_EXP, &cpu_dev, "IOCLQ_Get ERROR NULL qptr\n"); return -1; /* IOCLQ address error */ @@ -286,14 +269,12 @@ int32 IOCLQ_Get(IOCLQ *qptr, uint32 *old) /* see if the IOCLQ is empty */ if (qptr->ioclq_in == qptr->ioclq_out) { - sim_debug(DEBUG_EXP, &cpu_dev, "IOCLQ_Get IOCLQ empty\n"); +// sim_debug(DEBUG_EXP, &cpu_dev, "IOCLQ_Get IOCLQ empty\n"); return -1; /* IOCLQ is empty, tell caller */ } *old = qptr->ioclq_fifo[qptr->ioclq_out]; /* get the next entry */ qptr->ioclq_out += 1; /* next entry */ qptr->ioclq_out %= IOCLQ_SIZE; /* modulo IOCLQ size */ -// num = (qptr->ioclq_in - qptr->ioclq_out + IOCLQ_SIZE) % IOCLQ_SIZE; -// sim_debug(DEBUG_XIO, &cpu_dev, "IOCLQ_Get entry %06x leaving %02x entries\n", *old, num); return SCPE_OK; /* all OK */ } @@ -307,7 +288,6 @@ int32 IOCLQ_Num(IOCLQ *qptr) } /* calc entries */ num = (qptr->ioclq_in - qptr->ioclq_out + IOCLQ_SIZE) % IOCLQ_SIZE; -// sim_debug(DEBUG_EXP, &cpu_dev, "IOCLQ_Num #entries %02x\n", num); return num; /* one words/entry */ } @@ -321,16 +301,11 @@ t_stat set_inch(UNIT *uptr, uint32 inch_addr) { DIB *dibp = dib_chan[chan>>8]; /* get channel dib ptr */ CHANP *pchp = 0; /* for channel prog ptr */ - sim_debug(DEBUG_XIO, &cpu_dev, - "set_inch chan %04x inch addr %06x dibp %p\n", chan, inch_addr, dibp); - /* must be valid DIB pointer */ if (dibp == NULL) return SCPE_MEM; /* return memory error */ pchp = dibp->chan_prg; /* get parent channel prog ptr */ - sim_debug(DEBUG_XIO, &cpu_dev, - "set_inch chan %04x inch addr %06x pchp %p\n", chan, inch_addr, pchp); /* must be valid channel pointer */ if (pchp == NULL) return SCPE_MEM; /* return memory error */ @@ -348,6 +323,7 @@ t_stat set_inch(UNIT *uptr, uint32 inch_addr) { sim_debug(DEBUG_XIO, &cpu_dev, "set_inch chan %04x inch addr %06x chp %p\n", chan, inch_addr, chp); + /* now go through all the sub addresses for the channel and set inch addr */ for (i=0; i>16)&0x7f; /* get interrupt level */ - -// sim_debug(DEBUG_IRQ, &cpu_dev, - sim_debug(DEBUG_DETAIL, &cpu_dev, - "find_int_lev class F SPADC %08x chsa %04x lev %02x SPADI %08x INTS %08x\n", - spadent, chsa, inta, SPAD[inta+0x80], INTS[inta]); return(inta); /* return the level*/ } @@ -414,10 +385,6 @@ uint32 find_int_icb(uint16 chsa) "find_int_icb ERR chsa %04x icba %02x\n", chsa, icba); return 0; /* not found */ } -// sim_debug(DEBUG_IRQ, &cpu_dev, - sim_debug(DEBUG_DETAIL, &cpu_dev, - "find_int_icb icba %06x SPADC %08x chsa %04x lev %02x SPADI %08x INTS %08x\n", - icba, spadent, chsa, inta, SPAD[inta+0x80], INTS[inta]); return(icba); /* return the address */ } @@ -448,8 +415,6 @@ UNIT *find_unit_ptr(uint16 chsa) } uptr++; /* next unit */ } - sim_debug(DEBUG_EXP, &cpu_dev, - "find_unit_ptr ERR chsa %04x no match uptr %p\n", chsa, uptr); return NULL; /* device not found on system */ } @@ -463,20 +428,17 @@ CHANP *find_chanp_ptr(uint16 chsa) dibp = dib_unit[chsa]; /* get DIB pointer from unit address */ if (dibp == 0) { /* if zero, not defined on system */ - sim_debug(DEBUG_EXP, &cpu_dev, - "find_chanp_ptr ERR chsa %04x dibp %p\n", chsa, dibp); + sim_debug(DEBUG_EXP, &cpu_dev, "find_chanp_ptr ERR chsa %04x dibp %p\n", chsa, dibp); return NULL; /* tell caller */ } if ((chp = (CHANP *)dibp->chan_prg) == NULL) { /* must have channel information for each device */ - sim_debug(DEBUG_EXP, &cpu_dev, - "find_chanp_ptr ERR chsa %04x chp %p\n", chsa, chp); + sim_debug(DEBUG_EXP, &cpu_dev, "find_chanp_ptr ERR chsa %04x chp %p\n", chsa, chp); return NULL; /* tell caller */ } uptr = dibp->units; /* get the pointer to the units on this channel */ if (uptr == 0) { /* if zero, no devices defined on system */ - sim_debug(DEBUG_EXP, &cpu_dev, - "find_chanp_ptr ERR chsa %04x uptr %p\n", chsa, uptr); + sim_debug(DEBUG_EXP, &cpu_dev, "find_chanp_ptr ERR chsa %04x uptr %p\n", chsa, uptr); return NULL; /* tell caller */ } @@ -487,8 +449,7 @@ CHANP *find_chanp_ptr(uint16 chsa) uptr++; /* next UNIT */ chp++; /* next CHANP */ } - sim_debug(DEBUG_EXP, &cpu_dev, - "find_chanp_ptr ERR chsa %04x no match uptr %p\n", chsa, uptr); + sim_debug(DEBUG_EXP, &cpu_dev, "find_chanp_ptr ERR chsa %04x no match uptr %p\n", chsa, uptr); return NULL; /* device not found on system */ } @@ -507,14 +468,6 @@ int readfull(CHANP *chp, uint32 maddr, uint32 *word) } *word = RMW(maddr); /* get 1 word */ sim_debug(DEBUG_XIO, &cpu_dev, "READFULL read %08x from addr %08x\n", *word, maddr); -#if 0 -#define DO_DYNAMIC_DEBUG -#ifdef DO_DYNAMIC_DEBUG - if (maddr == 0x1aaf4 && *word == 0x017deda5) { - cpu_dev.dctrl |= DEBUG_INST; /* start instruction trace */ - } -#endif -#endif return 0; /* return OK */ } @@ -532,8 +485,6 @@ int readbuff(CHANP *chp) "readbuff PCHK addr %08x to big mem %08x status %04x\n", addr, MEMSIZE, chp->chan_status); chp->chan_byte = BUFF_CHNEND; /* force channel end & busy */ -//sim_debug(DEBUG_EXP, &cpu_dev, -//"readbuff BUFF_CHNEND chp %p chan_byte %04x\n", chp, chp->chan_byte); return 1; /* done, with error */ } chp->chan_buf = RMB(addr&MASK24); /* get 1 byte */ @@ -554,13 +505,10 @@ int writebuff(CHANP *chp) "writebuff PCHK addr %08x to big mem %08x status %04x\n", addr, MEMSIZE, chp->chan_status); chp->chan_byte = BUFF_CHNEND; /* force channel end & busy */ -//sim_debug(DEBUG_EXP, &cpu_dev, -//"writebuff BUFF_CHNEND chp %p chan_byte %04x\n", chp, chp->chan_byte); return 1; } addr &= MASK24; /* good address, write the byte */ - sim_debug(DEBUG_DATA, &cpu_dev, - "writebuff WRITE addr %06x DATA %08x status %04x\n", + sim_debug(DEBUG_DATA, &cpu_dev, "writebuff WRITE addr %06x DATA %08x status %04x\n", addr, chp->chan_buf, chp->chan_status); WMB(addr, chp->chan_buf); /* write byte to memory */ return 0; @@ -579,14 +527,14 @@ int32 load_ccw(CHANP *chp, int32 tic_ok) uint16 chan = get_chan(chp->chan_dev); /* our channel */ uint16 devstat = 0; - sim_debug(DEBUG_EXP, &cpu_dev, + sim_debug(DEBUG_XIO, &cpu_dev, "load_ccw @%06x entry chan_status[%04x] %04x\n", chp->chan_caw, chan, chp->chan_status); /* determine if channel DIB has a pre iocl processor */ if (dibp->iocl_io != NULL) { /* NULL if no function */ /* call the device controller to process the iocl */ int32 tempa = dibp->iocl_io(chp, tic_ok); /* process IOCL */ if (tempa != SCPE_OK) { /* see if OK */ - sim_debug(DEBUG_XIO, &cpu_dev, + sim_debug(DEBUG_EXP, &cpu_dev, "load_ccw iocl_io call return ERROR chan %04x cstat %01x\n", chan, tempa); } else { sim_debug(DEBUG_XIO, &cpu_dev, @@ -609,7 +557,7 @@ int32 load_ccw(CHANP *chp, int32 tic_ok) } loop: - sim_debug(DEBUG_EXP, &cpu_dev, + sim_debug(DEBUG_XIO, &cpu_dev, "load_ccw @%06x entry chan_status[%04x] %04x\n", chp->chan_caw, chan, chp->chan_status); /* Abort if we have any errors */ @@ -619,14 +567,6 @@ loop: return 1; } -#ifdef DONOTUSETHIS - /* Check if we have status modifier set */ - if (chp->chan_status & STATUS_MOD) { - chp->chan_caw += 8; /* move to next IOCD */ - chp->chan_status &= ~STATUS_MOD; /* turn off status modifier flag */ - } -#endif - /* Read in first CCW */ if (readfull(chp, chp->chan_caw, &word1) != 0) { /* read word1 from memory */ chp->chan_status |= STATUS_PCHK; /* memory read error, program check */ @@ -654,7 +594,7 @@ loop: /* if we did, use previous cmd value */ if (((chp->chan_info & INFO_SIOCD) == 0) && /* see if 1st IOCD in channel prog */ (chp->ccw_flags & FLAG_DC)) { /* last IOCD have DC set? */ - sim_debug(DEBUG_CMD, &cpu_dev, + sim_debug(DEBUG_XIO, &cpu_dev, "ec_iocl @%06x DO DC, ccw_flags %04x cmd %02x\n", chp->chan_caw, chp->ccw_flags, chp->ccw_cmd); } else @@ -662,42 +602,17 @@ loop: if (!MEM_ADDR_OK(word1 & MASK24)) { /* see if memory address invalid */ chp->chan_status |= STATUS_PCHK; /* bad, program check */ -//** uptr->SNS |= SNS_INAD; /* invalid address status */ sim_debug(DEBUG_EXP, &cpu_dev, "load_ccw bad IOCD1 chan_status[%04x] %04x\n", chan, chp->chan_status); return 1; /* error return */ } -#ifdef PROVIDE_FOR_EACH_DEVICE - /* validate the commands for the disk */ - switch (chp->ccw_cmd) { - case DSK_WD: case DSK_RD: case DSK_INCH: case DSK_NOP: case DSK_ICH: - case DSK_SCK: case DSK_XEZ: case DSK_LMR: case DSK_WSL: case DSK_RSL: - case DSK_IHA: case DSK_WTL: case DSK_RTL: case DSK_RAP: case DSK_TESS: - case DSK_FNSK: - /* reset status to on cyl & ready */ -// uptr->SNS2 = (SNS_UNR|SNS_ONC|SNS_USEL); - uptr->SNS2 = 0; - case DSK_SNS: - break; - default: - chp->chan_status |= STATUS_PCHK; /* program check for invalid cmd */ - uptr->SNS |= SNS_CMDREJ; /* cmd rejected */ - sim_debug(DEBUG_EXP, &cpu_dev, - "disk_iocl bad cmd chan_status[%04x] %04x\n", chan, chp->chan_status); - return 1; /* error return */ - } -#endif - chp->ccw_count = word2 & 0xffff; /* get 16 bit byte count from IOCD WD 2*/ if (chp->chan_info & INFO_SIOCD) { /* see if 1st IOCD in channel prog */ -//** /* 1st command can not be a TIC or NOP */ -//** if ((chp->ccw_cmd == 0x03) || (chp->ccw_cmd == CMD_TIC)) { /* 1st command can not be a TIC */ if (chp->ccw_cmd == CMD_TIC) { chp->chan_status |= STATUS_PCHK; /* program check for invalid tic */ -//** uptr->SNS |= SNS_CMDREJ; /* cmd rejected status */ sim_debug(DEBUG_EXP, &cpu_dev, "load_ccw TIC/NOP bad cmd chan_status[%04x] %04x\n", chan, chp->chan_status); @@ -715,8 +630,6 @@ loop: chan, chp->chan_caw, word1); chp->chan_status |= STATUS_PCHK; /* program check for invalid tic */ chp->chan_caw = word1 & MASK24; /* get new IOCD address */ -//** uptr->SNS |= SNS_CMDREJ; /* cmd rejected status */ -//** uptr->SNS |= SNS_INAD; /* invalid address status */ return 1; /* error return */ } tic_ok = 0; /* another tic not allowed */ @@ -728,9 +641,6 @@ loop: } chp->chan_caw = word1 & MASK24; /* get new IOCD address */ chp->chan_status |= STATUS_PCHK; /* program check for invalid tic */ -//** uptr->SNS |= SNS_CMDREJ; /* cmd rejected status */ -//** if (((word1 & MASK24) == 0) || (word1 & 0x3)) -//** uptr->SNS |= SNS_INAD; /* invalid address status */ sim_debug(DEBUG_EXP, &cpu_dev, "load_ccw TIC ERROR chan_status[%04x] %04x\n", chan, chp->chan_status); return 1; /* error return */ @@ -764,18 +674,15 @@ loop: return 1; /* error return */ } -#ifndef NOT_FOR_EVERYONE /* DC can only be used with a read/write cmd */ if (chp->ccw_flags & FLAG_DC) { if ((chp->ccw_cmd != 0x02) && (chp->ccw_cmd != 0x01)) { chp->chan_status |= STATUS_PCHK; /* program check for invalid DC */ -//** uptr->SNS |= SNS_CHER; /* chaining error */ sim_debug(DEBUG_EXP, &cpu_dev, "disk_iocl DC ERROR chan_status[%04x] %04x\n", chan, chp->chan_status); return 1; /* error return */ } } -#endif chp->chan_byte = BUFF_BUSY; /* busy & no bytes transferred yet */ @@ -826,7 +733,7 @@ loop: "load_ccw continue wait chsa %04x status %08x\n", chp->chan_dev, chp->chan_status); } -/*0816*/ } else + } else /* NOTE this code needed for MPX 1.X to run! */ /* see if command completed */ @@ -866,8 +773,6 @@ int chan_read_byte(uint16 chsa, uint8 *data) if (chp->ccw_count == 0) { /* see if more data required */ if ((chp->ccw_flags & FLAG_DC) == 0) { /* see if Data Chain */ chp->chan_byte = BUFF_CHNEND; /* buffer end too */ -//sim_debug(DEBUG_EXP, &cpu_dev, -//"chan_read BUFF_CHNEND chp %p chan_byte %04x\n", chp, chp->chan_byte); sim_debug(DEBUG_XIO, &cpu_dev, "chan_read_byte no DC chan end, cnt %04x addr %06x chan %04x\n", chp->ccw_count, chp->ccw_addr, chan); @@ -909,8 +814,6 @@ int test_write_byte_end(uint16 chsa) if (chp->ccw_count == 0) { if ((chp->ccw_flags & FLAG_DC) == 0) { /* see if we have data chaining */ chp->chan_byte = BUFF_CHNEND; /* thats all the data we want */ -//sim_debug(DEBUG_EXP, &cpu_dev, -//"test_write_byte BUFF_CHNEND chp %p chan_byte %04x\n", chp, chp->chan_byte); return 1; /* return done */ } } @@ -956,8 +859,6 @@ int chan_write_byte(uint16 chsa, uint8 *data) return 1; /* return done error */ } else { /* we have data chaining, process iocl */ - sim_debug(DEBUG_DETAIL, &cpu_dev, - "chan_write_byte got DC, calling load_ccw chan %04x\n", chan); if (load_ccw(chp, 1)) { /* process data chaining */ sim_debug(DEBUG_EXP, &cpu_dev, "chan_write_byte with DC error, cnt %04x addr %06x chan %04x\n", @@ -1044,14 +945,9 @@ void chan_end(uint16 chsa, uint16 flags) { chsa, flags, chp->chan_status, chp->ccw_cmd); chp->chan_byte = BUFF_BUSY; /* we are empty & still busy now */ -//sim_debug(DEBUG_EXP, &cpu_dev, "chan_end1 BUFF_BUSY chp %p chan_byte %04x\n", chp, chp->chan_byte); chp->chan_status |= STATUS_CEND; /* set channel end */ chp->chan_status |= ((uint16)flags); /* add in the callers flags */ - sim_debug(DEBUG_DETAIL, &cpu_dev, - "chan_end SLI test1 chsa %04x ccw_flags %04x count %04x status %04x\n", - chsa, chp->ccw_flags, chp->ccw_count, chp->chan_status); - /* read/write must have none-zero byte count */ /* all others can be zero, except NOP, which must be 0 */ /* a NOP is Control command 0x03 with no modifier bits */ @@ -1068,10 +964,6 @@ void chan_end(uint16 chsa, uint16 flags) { } } - sim_debug(DEBUG_DETAIL, &cpu_dev, - "chan_end SLI2 test chsa %04x ccw_flags %04x status %04x\n", - chsa, chp->ccw_flags, chp->chan_status); - /* Diags do not want SLI if we have no device end status */ if ((chp->chan_status & STATUS_LENGTH) && ((chp->chan_status & STATUS_DEND) == 0)) chp->chan_status &= ~STATUS_LENGTH; @@ -1293,8 +1185,6 @@ t_stat checkxio(uint16 lchsa, uint32 *status) { uint32 spadent; uint16 rchan, rchsa; /* the real channel number */ - sim_debug(DEBUG_DETAIL, &cpu_dev, "checkxio entry lchsa %04x\n", lchsa); - /* get the device entry for the logical channel in SPAD */ spadent = SPAD[lchan]; /* get spad device entry for logical channel */ rchan = (spadent & 0x7f00) >> 8; /* get real channel */ @@ -1316,16 +1206,21 @@ nothere: } inta = ((~spadent)>>16)&0x7f; /* get channel interrupt level */ chp->chan_int = inta; /* make sure it is set in channel */ + dptr = get_dev(uptr); /* pointer to DEVICE structure */ /* check for the device being defined and attached in simh */ if ((uptr->flags & UNIT_ATTABLE) && ((uptr->flags & UNIT_ATT) == 0)) { sim_debug(DEBUG_EXP, &cpu_dev, "checkxio lchsa %04x rchsa %04x is not attached, CC3 return\n", lchsa, rchsa); - *status = CC3BIT; /* not attached, so error CC3 */ + /* UTX wants CC1 on "mt offline" call. If not, UTX loops forever */ + if ((dptr != NULL) && + (DEV_TYPE(dptr) == DEV_TAPE)) /* see if this is a tape */ + *status = CC1BIT; /* CCs = 1, not busy */ + else + *status = CC3BIT; /* not attached, so error CC3 */ return SCPE_OK; /* not found, CC3 */ } - dptr = get_dev(uptr); /* pointer to DEVICE structure */ /* try this as MFP says it returns 0 on OK */ if (dptr->flags & DEV_CHAN) *status = 0; /* CCs = 0, OK return */ @@ -1379,8 +1274,6 @@ t_stat startxio(uint16 lchsa, uint32 *status) { #endif DEVICE *dptr; - sim_debug(DEBUG_XIO, &cpu_dev, "startxio entry logical chsa %04x\n", lchsa); - /* get the device entry for the logical channel in SPAD */ spadent = SPAD[lchan]; /* get spad device entry for logical channel */ inta = ((~spadent)>>16)&0x7f; /* get interrupt level */ @@ -1434,16 +1327,15 @@ missing: chsa, chp, (uptr->flags & UNIT_ATTABLE)?1:0, (uptr->flags & UNIT_ATT)?1:0, (uptr->flags & UNIT_DIS)?1:0); - if ((uptr->flags & UNIT_ATTABLE) && ((uptr->flags & UNIT_ATT) == 0) && - (uptr->flags & UNIT_SUBCHAN) == 0) { /* is unit attached? */ + /* is unit marked disabled? */ + if ((uptr->flags & UNIT_DIS) == 1) { sim_debug(DEBUG_EXP, &cpu_dev, - "startxio chsa %04x device not present, CC3 returned flags %08x\n", chsa, uptr->flags); + "startxio chsa %04x device disabled, CC3 returned flags %08x\n", chsa, uptr->flags); *status = CC3BIT; /* not attached, so error CC3 */ return SCPE_OK; /* not found, CC3 */ } #ifdef FOR_DEBUG -// inta = find_int_lev(chsa); /* Interrupt Level for channel */ if ((INTS[inta]&INTS_ACT) || (SPAD[inta+0x80]&SINT_ACT)) { /* look for level active */ /* just output a warning */ sim_debug(DEBUG_XIO, &cpu_dev, @@ -1478,7 +1370,6 @@ missing: } } -// chan_icb = find_int_icb(chsa); /* Interrupt level context block address */ sim_debug(DEBUG_XIO, &cpu_dev, "startxio int spad %08x icb %06x inta %02x chan %04x\n", SPAD[inta+0x80], chan_icb, inta, chan); @@ -1487,7 +1378,6 @@ missing: /* before calling load_ccw which does it again for each IOCL step */ iocla = RMW(chan_icb+16); /* iocla is in wd 4 of ICB */ word1 = RMW(iocla & MASK24); /* get 1st IOCL word */ -// incha = word1 & MASK24; /* should be inch addr */ word2 = RMW((iocla + 4) & MASK24); /* get 2nd IOCL word */ cmd = (word1 >> 24) & 0xff; /* get channel cmd from IOCL */ chp = find_chanp_ptr(chsa&0x7f00); /* find the parent chanp pointer */ @@ -1504,7 +1394,6 @@ missing: chsa, iocla, RMW(iocla), RMW(iocla+4)); iocla = RMW(chan_icb+16); /* iocla is in wd 4 of ICB */ -// incha = chp->chan_inch_addr; /* get inch address */ sim_debug(DEBUG_CMD, &cpu_dev, "$$$ SIO %04x %04x cmd %02x ccw_flags %04x\n", chsa, chan, cmd, word2>>16); @@ -1586,8 +1475,6 @@ missing: /* Queue us to continue IOCL from cpu level & make busy */ chp->chan_byte = BUFF_NEXT; /* have main pick us up */ chp->chan_info = INFO_SIOCD; /* show first IOCD in channel prog */ - sim_debug(DEBUG_EXP, &cpu_dev, - "startxio BUFF_NEXT chp %p chan_byte %04x\n", chp, chp->chan_byte); RDYQ_Put(chsa); /* queue us up */ sim_debug(DEBUG_XIO, &cpu_dev, "$$$ SIO queued chsa %04x iocla %06x IOCD1 %08x IOCD2 %08x\n", @@ -1597,8 +1484,8 @@ missing: if (waitqcnt == 0) /* test for UTX delay */ // waitqcnt = 20; /* tell cpu to wait 20 instructions before int */ // waitqcnt = 35; /* tell cpu to wait 20 instructions before int */ - waitqcnt = 25; /* tell cpu to wait 20 instructions before int */ //XX waitqcnt = 15; /* tell cpu to wait 20 instructions before int */ + waitqcnt = 25; /* tell cpu to wait 20 instructions before int */ *status = CC1BIT; /* CCs = 1, SIO accepted & queued, no echo status */ sim_debug(DEBUG_XIO, &cpu_dev, "$$$ SIO done chsa %04x status %08x iocla %08x CC's %08x\n", @@ -1623,8 +1510,6 @@ t_stat testxio(uint16 lchsa, uint32 *status) { /* test XIO */ rchsa = (spadent & 0x7f00); /* get real channel suba of zero */ rchan = rchsa >> 8; /* get real channel */ - sim_debug(DEBUG_XIO, &cpu_dev, "$$ TIO entry lchsa %04x rchsa %02x\n", lchsa, rchsa); - /* get the device entry for the channel in SPAD */ dibp = dib_chan[rchan]; /* get the DIB pointer */ chp = find_chanp_ptr(rchan << 8); /* find the device chanp pointer */ @@ -1693,9 +1578,7 @@ t_stat testxio(uint16 lchsa, uint32 *status) { /* test XIO */ } /* nothing going on, so say all OK */ -// *status = CC1BIT; /* request accepted, no status, so CC1 */ WMW(chan_icb+20, 0); /* post sw addr 0 in ICB+5w & reset CCs */ -// *status = 0; /* no status stored from TIO, so no CC */ *status = CC1BIT; /* request accepted, no status, so CC1 */ INTS[inta] &= ~INTS_REQ; /* clear any level request if no status */ sim_debug(DEBUG_XIO, &cpu_dev, @@ -1720,8 +1603,6 @@ t_stat stopxio(uint16 lchsa, uint32 *status) { /* stop XIO */ rchan = (spadent & 0x7f00) >> 8; /* get real channel */ rchsa = (rchan << 8) | (lchsa & 0xff); /* get the read chan & suba */ - sim_debug(DEBUG_XIO, &cpu_dev, "STPIO entry lchsa %04x rchsa %04x\n", lchsa, rchsa); - /* get the device entry for the logical channel in SPAD */ dibp = dib_unit[rchsa]; /* get the DIB pointer */ chp = find_chanp_ptr(rchsa); /* find the device chanp pointer */ @@ -1746,16 +1627,11 @@ t_stat stopxio(uint16 lchsa, uint32 *status) { /* stop XIO */ chp->chan_int = inta; /* make sure it is set in channel */ itva = SPAD[0xf1] + (inta<<2); /* int vector address */ chan_icb = RMW(itva); /* Interrupt context block addr */ -// chan_icb = find_int_icb(chsa); /* Interrupt level context block address */ -// inta = find_int_lev(chsa); /* Interrupt Level for channel */ iocla = RMW(chan_icb+16); /* iocla is in wd 4 of ICB */ sim_debug(DEBUG_CMD, &cpu_dev, "STPIO busy test rchsa %04x cmd %02x ccw_flags %04x IOCD1 %08x IOCD2 %08x\n", rchsa, chp->ccw_cmd, chp->ccw_flags, M[iocla>>2], M[(iocla+4)>>2]); - sim_debug(DEBUG_CMD, &cpu_dev, "$$$ STPIO %04x %02x %04x\n", - rchsa, chp->ccw_cmd, chp->ccw_flags); - if ((chp->chan_byte & BUFF_BUSY) == 0) { /* the channel is not busy, so return OK */ *status = CC1BIT; /* request accepted, no status, so CC1 */ @@ -1791,9 +1667,8 @@ t_stat stopxio(uint16 lchsa, uint32 *status) { /* stop XIO */ "$$$ STOPXIO END2 rchsa %04x rchan %04x cmd %02x ccw_flags %04x status %04x\n", rchsa, rchan, chp->ccw_cmd, chp->ccw_flags, *status); /* change status from BUFF_POST to BUFF_DONE */ -/*082420*/ if (chp->chan_byte == BUFF_POST) { -/*082420*/ chp->chan_byte = BUFF_DONE; /* show done & not busy */ -//sim_debug(DEBUG_EXP, &cpu_dev, "STPIO BUFF_DONE1 chp %p chan_byte %04x\n", chp, chp->chan_byte); + if (chp->chan_byte == BUFF_POST) { + chp->chan_byte = BUFF_DONE; /* show done & not busy */ } return SCPE_OK; /* CC2 & all OK */ } @@ -1807,9 +1682,6 @@ t_stat stopxio(uint16 lchsa, uint32 *status) { /* stop XIO */ return SCPE_OK; /* CC1 & all OK */ } } - /* the device is not busy, so cmd has not started */ - sim_debug(DEBUG_EXP, &cpu_dev, - "STPIO BUFF_DONE2 chp %p chan_byte %04x\n", chp, chp->chan_byte); /* the channel is not busy, so return OK */ *status = CC1BIT; /* request accepted, no status, so CC1 */ sim_debug(DEBUG_CMD, &cpu_dev, @@ -1822,8 +1694,6 @@ t_stat stopxio(uint16 lchsa, uint32 *status) { /* stop XIO */ /* set the return to CC3BIT & CC4BIT causes infinite loop in MPX1X */ /* restore code to old CC1BIT return 12/21/2020 */ *status = CC1BIT; /* request accepted, no status, so CC1 */ -// *status = CC4BIT; /*1204*/ /* device is busy, so CC4 */ -// *status = CC3BIT|CC4BIT; /*1204*/ /* device is busy, so CC3 & CC4 */ /* reset the DC or CC bits to force completion after current IOCD */ chp->ccw_flags &= ~(FLAG_DC|FLAG_CC); /* reset chaining bits */ sim_debug(DEBUG_CMD, &cpu_dev, @@ -1848,8 +1718,6 @@ t_stat rschnlxio(uint16 lchsa, uint32 *status) { /* reset channel XIO */ rchan = (spadent & 0x7f00) >> 8; /* get real channel */ rchsa = rchan << 8; /* get the real chan & zero suba */ - sim_debug(DEBUG_XIO, &cpu_dev, "rschnlxio entry lchan %04x rchan %04x\n", lchan, rchan); - /* get the device entry for the logical channel in SPAD */ dibp = dib_unit[rchsa]; /* get the channel device information pointer */ chp = find_chanp_ptr(rchsa); /* find the channel chanp pointer */ @@ -1892,10 +1760,9 @@ t_stat rschnlxio(uint16 lchsa, uint32 *status) { /* reset channel XIO */ chp = find_chanp_ptr(rchsa); /* find the chanp pointer */ if (chp == 0) continue; /* not used */ -/*0202*/uptr = chp->unitptr; /* get the unit ptr */ + uptr = chp->unitptr; /* get the unit ptr */ /* see if we have a rschnl device entry */ -//sim_debug(DEBUG_EXP, &cpu_dev, "rschnlxio dib->rschnl_io %p\n", dibp->rschnl_io); if (dibp->rschnl_io != NULL) { /* NULL if no rschnl_io function */ /* call the device controller to process rschnl */ j = dibp->rschnl_io(uptr); /* get status from device */ @@ -1904,7 +1771,6 @@ t_stat rschnlxio(uint16 lchsa, uint32 *status) { /* reset channel XIO */ } chp->chan_status = 0; /* clear the channel status */ chp->chan_byte = BUFF_EMPTY; /* no data yet */ -//sim_debug(DEBUG_EXP, &cpu_dev, "rschnlxio BUFF_EMPTY chp %p rchsa %04x\n", chp, rchsa); chp->ccw_addr = 0; /* clear buffer address */ chp->chan_caw = 0x0; /* clear IOCD address */ chp->ccw_count = 0; /* channel byte count 0 bytes*/ @@ -1955,16 +1821,12 @@ t_stat haltxio(uint16 lchsa, uint32 *status) { /* halt XIO */ /* the haltio opcode processing software has already checked for F class */ inta = ((~spadent)>>16)&0x7f; /* get channel interrupt level */ chp->chan_int = inta; /* make sure it is set in channel */ -// inta = ((spadent & 0x007f0000) >> 16); /* 1's complement of chan int level */ -// inta = 127 - inta; /* get positive int level */ -// spadent = SPAD[inta + 0x80]; /* get interrupt spad entry */ sim_debug(DEBUG_XIO, &cpu_dev, "HIO int spad %08x inta %02x rchan %02x\n", spadent, inta, rchan); /* get the address of the interrupt IVL in main memory */ itva = SPAD[0xf1] + (inta<<2); /* int vector address */ chan_icb = RMW(itva); /* Interrupt context block addr */ iocla = RMW(chan_icb+16); /* iocla is in wd 4 of ICB */ -// incha = RMW(chan_icb+20); /* post inch addr in ICB+5w */ sim_debug(DEBUG_XIO, &cpu_dev, "$$ HIO busy test byte %02x rchsa %04x cmd %02x ccw_flags %04x IOCD1 %08x IOCD2 %08x\n", @@ -1996,8 +1858,8 @@ t_stat haltxio(uint16 lchsa, uint32 *status) { /* halt XIO */ "$$$ HIO END2 rchsa %04x cmd %02x ccw_flags %04x status %04x\n", rchsa, chp->ccw_cmd, chp->ccw_flags, *status); /* change status from BUFF_POST to BUFF_DONE */ -/*082420*/ if (chp->chan_byte == BUFF_POST) { -/*082420*/ chp->chan_byte = BUFF_DONE; /* show done & not busy */ + if (chp->chan_byte == BUFF_POST) { + chp->chan_byte = BUFF_DONE; /* show done & not busy */ sim_debug(DEBUG_EXP, &cpu_dev, "HIO BUFF_DONE1 chp %p chan_byte %04x\n", chp, chp->chan_byte); } @@ -2007,8 +1869,6 @@ t_stat haltxio(uint16 lchsa, uint32 *status) { /* halt XIO */ chp->ccw_count = 0; /* zero the count */ /* The diags want the interrupt for the disk */ *status = CC1BIT; /* request accepted, no status, so CC1 */ -//BAD *status = CC4BIT; /* request accepted, no status, so CC1 */ -//BAD *status = 0; /* request accepted, no status, so CC1 */ sim_debug(DEBUG_CMD, &cpu_dev, "$$$ HIO END2 ECHO rchsa %04x cmd %02x ccw_flags %04x status %04x\n", rchsa, chp->ccw_cmd, chp->ccw_flags, *status); @@ -2045,14 +1905,12 @@ t_stat haltxio(uint16 lchsa, uint32 *status) { /* halt XIO */ sim_debug(DEBUG_CMD, &cpu_dev, "$$$ HIO END1 not busy return rchsa %04x cmd %02x ccw_flags %04x status %04x\n", rchsa, chp->ccw_cmd, chp->ccw_flags, *status); -#ifndef JUNK +#ifndef MAYBE_NOT chp->chan_byte = BUFF_DONE; /* we are done */ -sim_debug(DEBUG_EXP, &cpu_dev, "haltxio BUFF_DONE chp %p chan_byte %04x\n", chp, chp->chan_byte); -/*1204*/chp->chan_status = (STATUS_DEND|STATUS_CEND|STATUS_EXPT); + chp->chan_status = (STATUS_DEND|STATUS_CEND|STATUS_EXPT); store_csw(chp); /* store the status */ /* change chan_byte to BUFF_POST */ chp->chan_byte = BUFF_POST; /* show done with data */ -//sim_debug(DEBUG_EXP, &cpu_dev, "haltxio BUFF_POST chp %p chan_byte %04x\n", chp, chp->chan_byte); chp->chan_status = 0; /* no status anymore */ chp->ccw_cmd = 0; /* no command anymore */ irq_pend = 1; /* flag to test for int condition */ @@ -2069,8 +1927,6 @@ sim_debug(DEBUG_EXP, &cpu_dev, "haltxio BUFF_DONE chp %p chan_byte %04x\n", chp, /* reset the DC or CC bits to force completion */ chp->ccw_flags &= ~(FLAG_DC|FLAG_CC); /* reset chaining bits */ chp->chan_byte = BUFF_BUSY; /* wait for post_csw to be done */ -//sim_debug(DEBUG_EXP, &cpu_dev, "HIO BUFF_DONE3 chp %p chan_byte %04x\n", chp, chp->chan_byte); -// chp->ccw_count = 0; /* zero the count */ sim_cancel(uptr); /* cancel timer service */ chp->chan_status &= ~STATUS_BUSY; /* remove BUSY status bit */ chan_end(rchsa, SNS_CHNEND|SNS_DEVEND); /* show I/O complete */ @@ -2085,15 +1941,13 @@ sim_debug(DEBUG_EXP, &cpu_dev, "haltxio BUFF_DONE chp %p chan_byte %04x\n", chp, "$$$ HIO END4 rchsa %04x cmd %02x ccw_flags %04x status %04x\n", rchsa, chp->ccw_cmd, chp->ccw_flags, *status); /* change status from BUFF_POST to BUFF_DONE */ -/*082420*/ if (chp->chan_byte == BUFF_POST) { -/*082420*/ chp->chan_byte = BUFF_DONE; /* show done & not busy */ -//sim_debug(DEBUG_EXP, &cpu_dev, "HIO BUFF_DONE4 chp %p chan_byte %04x\n", chp, chp->chan_byte); + if (chp->chan_byte == BUFF_POST) { + chp->chan_byte = BUFF_DONE; /* show done & not busy */ } return SCPE_OK; /* CC2 & all OK */ } } chp->chan_byte = BUFF_DONE; /* chan prog done */ -sim_debug(DEBUG_EXP, &cpu_dev, "HIO BUFF_DONE5 chp %p chan_byte %04x\n", chp, chp->chan_byte); /* the channel is not busy, so return OK */ *status = CC1BIT; /* request accepted, no status, so CC1 */ sim_debug(DEBUG_CMD, &cpu_dev, @@ -2117,8 +1971,6 @@ t_stat grabxio(uint16 lchsa, uint32 *status) { /* grab controller XIO n/u * rchan = (spadent & 0x7f00) >> 8; /* get real channel */ rchsa = (rchan << 8) | (lchsa & 0xff); /* merge sa to real channel */ - sim_debug(DEBUG_XIO, &cpu_dev, "GRIO entry lchsa %04x rchsa %04x\n", lchsa, rchsa); - /* get the device entry for the logical channel in SPAD */ dibp = dib_unit[rchsa]; /* get the DIB pointer */ chp = find_chanp_ptr(rchsa); /* find the device chanp pointer */ @@ -2152,8 +2004,6 @@ t_stat grabxio(uint16 lchsa, uint32 *status) { /* grab controller XIO n/u * /* returning No CC's causes MPX1X to loop forever */ /* so restore returning CC1 */ *status = 0; /* return no CC's */ -// *status = CC1BIT; /* return no CC's */ -// *status = CC3BIT|CC4BIT; /* busy */ } else { /* diags want unsupported transaction for disk */ *status = CC2BIT|CC4BIT; /* unsupported transaction */ @@ -2236,7 +2086,6 @@ t_stat rsctlxio(uint16 lchsa, uint32 *status) { /* reset controller XIO */ } chp->chan_status = 0; /* clear the channel status */ chp->chan_byte = BUFF_EMPTY; /* no data yet */ -//sim_debug(DEBUG_EXP, &cpu_dev, "rsctlxio BUFF_EMPTY chp %p chan_byte %04x\n", chp, chp->chan_byte); chp->ccw_addr = 0; /* clear buffer address */ chp->chan_caw = 0x0; /* clear IOCD address */ chp->ccw_count = 0; /* channel byte count 0 bytes*/ @@ -2289,7 +2138,6 @@ t_stat chan_boot(uint16 chsa, DEVICE *dptr) { chp->chan_status = 0; /* clear the channel status */ chp->chan_dev = chsa; /* save our address (ch/sa) */ chp->chan_byte = BUFF_EMPTY; /* no data yet */ -//sim_debug(DEBUG_EXP, &cpu_dev, "chan_boot BUFF_EMPTY chp %p chan_byte %04x\n", chp, chp->chan_byte); chp->ccw_addr = 0; /* start loading at loc 0 */ chp->chan_caw = 0x0; /* set IOCD address to memory location 0 */ chp->ccw_count = 0; /* channel byte count 0 bytes*/ @@ -2310,11 +2158,10 @@ t_stat chan_boot(uint16 chsa, DEVICE *dptr) { /* start processing the boot IOCL at loc 0 */ if (load_ccw(chp, 0)) { /* load IOCL starting from location 0 */ - sim_debug(DEBUG_XIO, &cpu_dev, "Channel Boot Error return from load_ccw chan %04x status %08x\n", + sim_debug(DEBUG_EXP, &cpu_dev, "Channel Boot Error return from load_ccw chan %04x status %08x\n", chan, chp->chan_status); chp->ccw_flags = 0; /* clear the command flags */ chp->chan_byte = BUFF_DONE; /* done with errors */ -//sim_debug(DEBUG_EXP, &cpu_dev, "chan_boot BUFF_DONE chp %p chan_byte %04x\n", chp, chp->chan_byte); loading = 0; /* show we are done loading from the boot device */ return SCPE_IOERR; /* return error */ } @@ -2355,7 +2202,7 @@ uint32 cont_chan(uint16 chsa) chsa, chp->chan_status); /*NOTE*/ /* if we have an error, we would loop forever if the CC bit was set */ /* the only way to stop was to do a kill */ -/*082320*/ chp->ccw_flags &= ~(FLAG_DC|FLAG_CC); /* reset chaining bits */ + chp->ccw_flags &= ~(FLAG_DC|FLAG_CC); /* reset chaining bits */ /* DIAG's want CC1 with memory access error */ if (chp->chan_status & STATUS_PCHK) { chp->chan_status &= ~STATUS_LENGTH; /* clear incorrect length */ @@ -2429,12 +2276,8 @@ uint32 scan_chan(uint32 *ilev) { /* set BIT 1 to show status stored */ WMW(tempa, sw1|BIT1); /* save sa & IOCD address in status WD 1 loc */ WMW(tempa+4, sw2); /* save status and residual cnt in status WD 2 loc */ - /* now store the status dw address into word 5 of the ICB for the channel */ - /* there is no icb when we are ipl booting, so skip this */ -//NO_GOOD WMW(chan_icb+20, tempa|BIT1); /* post sw addr in ICB+5w & set CC2 in INCH addr */ #endif chp->chan_byte = BUFF_DONE; /* we are done */ -//sim_debug(DEBUG_EXP, &cpu_dev, "scan_chan BUFF_DONE chp %p chan_byte %04x\n", chp, chp->chan_byte); sim_debug(DEBUG_IRQ, &cpu_dev, "LOADING %06x %04x FIFO #%1x read inch %06x sw1 %08x sw2 %08x\n", chp->chan_caw, chan, FIFO_Num(chan), tempa, sw1|BIT1, sw2); @@ -2446,10 +2289,8 @@ uint32 scan_chan(uint32 *ilev) { /* see if we are able to look for ints */ if (irq_pend == 0) /* pending int? */ return 0; /* no, done */ -#ifndef TRY_121420_NOGOOD if (CPUSTATUS & BIT24) /* interrupts blocked? */ return 0; /* yes, done */ -#endif /* ints not blocked, so look for highest requesting interrupt */ for (i=0; i<112; i++) { @@ -2457,14 +2298,6 @@ uint32 scan_chan(uint32 *ilev) { continue; /* skip this one */ if (SPAD[i+0x80] == 0xffffffff) /* not initialize? */ continue; /* skip this one */ - /* this is a bug fix for MPX 1.x restart command */ -// if (SPAD[i+0x80] == 0xefffffff) /* not initialize? */ -// continue; /* skip this one */ -#ifdef CAN_BE_DISABLED_090720 - if ((INTS[i] & INTS_ENAB) == 0) /* ints must be enabled */ - continue; /* skip this one */ -#endif - if (INTS[i] & INTS_REQ) /* if already requesting, skip */ continue; /* skip this one */ @@ -2483,7 +2316,7 @@ uint32 scan_chan(uint32 *ilev) { sim_debug(DEBUG_EXP, &cpu_dev, "scan_chan FIFO REQ FIFO #%1x irq %02x SPAD %08x INTS %08x\n", FIFO_Num(SPAD[i+0x80] & 0x7f00), i, SPAD[i+0x80], INTS[i]); -/*1231*/ irq_pend = 1; /* we have pending interrupt */ + irq_pend = 1; /* we have pending interrupt */ continue; } } @@ -2491,13 +2324,9 @@ uint32 scan_chan(uint32 *ilev) { /* cannot make anyone active if ints are blocked */ if ((CPUSTATUS & BIT24) || (waitqcnt)) { /* interrupts blocked? */ if (waitqcnt) /* doing wait delay? */ - sim_debug(DEBUG_DETAIL, &cpu_dev, -// sim_debug(DEBUG_IRQ, &cpu_dev, - "scan_chan waitqcnt %02x\n", waitqcnt); + sim_debug(DEBUG_DETAIL, &cpu_dev, "scan_chan waitqcnt %02x\n", waitqcnt); if (CPUSTATUS & BIT24) /* interrupts blocked? */ - sim_debug(DEBUG_DETAIL, &cpu_dev, -// sim_debug(DEBUG_IRQ, &cpu_dev, - "scan_chan INTS blocked!\n"); + sim_debug(DEBUG_DETAIL, &cpu_dev, "scan_chan INTS blocked!\n"); goto tryme; /* needed for MPX */ } @@ -2511,8 +2340,7 @@ uint32 scan_chan(uint32 *ilev) { if (SPAD[i+0x80] == 0xefffffff) /* not initialize? */ continue; /* skip this one */ if ((INTS[i]&INTS_ACT) || (SPAD[i+0x80]&SINT_ACT)) { /* look for level active */ -// sim_debug(DEBUG_DETAIL, &cpu_dev, - sim_debug(DEBUG_IRQ, &cpu_dev, + sim_debug(DEBUG_DETAIL, &cpu_dev, "scan_chan INTS ACT irq %02x SPAD %08x INTS %08x\n", i, SPAD[i+0x80], INTS[i]); return 0; /* this level active, so stop looking */ @@ -2527,8 +2355,7 @@ uint32 scan_chan(uint32 *ilev) { if (((INTS[i] & INTS_ENAB) && (INTS[i] & INTS_REQ)) || ((SPAD[i+0x80] & SINT_ENAB) && (INTS[i] & INTS_REQ))) { -// sim_debug(DEBUG_DETAIL, &cpu_dev, - sim_debug(DEBUG_IRQ, &cpu_dev, + sim_debug(DEBUG_DETAIL, &cpu_dev, "scan_chan highest int req irq %02x SPAD %08x INTS %08x\n", i, SPAD[i+0x80], INTS[i]); @@ -2571,9 +2398,8 @@ uint32 scan_chan(uint32 *ilev) { /* change status from BUFF_POST to BUFF_DONE */ /* if not BUFF_POST we have a PPCI or channel busy interrupt */ /* so leave the channel status alone */ -/*082420*/ if (chp->chan_byte == BUFF_POST) { -/*082420*/ chp->chan_byte = BUFF_DONE; /* show done & not busy */ -//sim_debug(DEBUG_EXP, &cpu_dev, "scan_chanx BUFF_DONE chp %p chan_byte %04x\n", chp, chp->chan_byte); + if (chp->chan_byte == BUFF_POST) { + chp->chan_byte = BUFF_DONE; /* show done & not busy */ } } else { sim_debug(DEBUG_IRQ, &cpu_dev, @@ -2661,9 +2487,8 @@ t_stat chan_set_devs() { continue; if ((dptr->flags & DEV_DIS) || /* Skip disabled devices */ ((dibp->chan_prg) == NULL)) { /* must have channel info for each device */ - chsa = GET_UADDR(uptr->u3); /* ch/sa value */ -// printf("Device %s chsa %04x not set up dibp %p\n", dptr->name, chsa, dibp); +//printf("Device %s chsa %04x not set up dibp %p\n", dptr->name, chsa, dibp); continue; } @@ -2671,14 +2496,13 @@ t_stat chan_set_devs() { /* Check if address is in unit or dev entry */ for (j = 0; j < dptr->numunits; j++) { /* loop through unit entries */ chsa = GET_UADDR(uptr->u3); /* ch/sa value */ -// printf("Setup device %s%d chsa %04x type %03d dibp %p\n", -// dptr->name, j, chsa, GET_TYPE(uptr->flags), dibp); +//printf("Setup device %s%d chsa %04x type %02x dibp %p\n", +//dptr->name, j, chsa, GET_TYPE(uptr->flags), dibp); /* zero some channel data loc's for device */ chp->unitptr = uptr; /* set the unit back pointer */ chp->chan_status = 0; /* clear the channel status */ chp->chan_dev = chsa; /* save our address (ch/sa) */ chp->chan_byte = BUFF_EMPTY; /* no data yet */ -//sim_debug(DEBUG_EXP, &cpu_dev, "chan_set_devs BUFF_EMPTY chp %p chan_byte %04x\n", chp, chp->chan_byte); chp->ccw_addr = 0; /* start loading at loc 0 */ chp->chan_caw = 0; /* set IOCD address to memory location 0 */ chp->ccw_count = 0; /* channel byte count 0 bytes*/ @@ -2694,10 +2518,10 @@ t_stat chan_set_devs() { if (dptr->flags & DEV_CHAN) { /* see if channel address already defined */ if (dib_chan[get_chan(chsa)] != 0) { -// printf("Channel mux %04x already defined, aborting\n", chsa); +//printf("Channel mux %04x already defined, aborting\n", chsa); return SCPE_IERR; /* no, arg error */ } -// printf("Setting Channel mux %04x dibp %p\n", chsa, dibp); +//printf("Setting Channel mux %04x dibp %p\n", chsa, dibp); /* channel mux, save dib for channel */ dib_chan[get_chan(chsa)] = dibp; if (dibp->dev_ini != NULL) /* if there is an init routine, call it now */ @@ -2705,13 +2529,13 @@ t_stat chan_set_devs() { } else { /* we have unit 0 of non-IOP/MFP device */ if (dib_unit[chsa] != 0) { -// printf("Channel/Dev %04x already defined\n", chsa); +//printf("Channel/Dev %04x already defined\n", chsa); return SCPE_IERR; /* no, arg error */ } else { /* channel mux, save dib for channel */ /* for now, save any zero dev as chan */ if (chsa) { -// printf("Setting Channel zero unit 0 device %04x dibp %p\n", chsa, dibp); +//printf("Setting Channel zero unit 0 device %04x dibp %p\n", chsa, dibp); dib_unit[chsa] = dibp; /* no, save the dib address */ if (dibp->dev_ini != NULL) /* if there is an init routine, call it now */ dibp->dev_ini(uptr, 1); /* init the channel */ @@ -2721,7 +2545,7 @@ t_stat chan_set_devs() { } else { /* see if address already defined */ if (dib_unit[chsa] != 0) { -// printf("Channel/SubAddress %04x multiple defined, aborting\n", chsa); +//printf("Channel/SubAddress %04x multiple defined, aborting\n", chsa); return SCPE_IERR; /* no, arg error */ } dib_unit[chsa] = dibp; /* no, save the dib address */ @@ -2743,10 +2567,10 @@ t_stat chan_set_devs() { if (dib_unit[i<<8]) { /* write dibp to channel array */ dib_chan[i] = dib_unit[i<<8]; /* save the channel dib */ -// printf("Chan_set_dev new Channel %04x defined at dibp %p\n", i<<8, dib_unit[i<<8]); +//printf("Chan_set_dev new Channel %04x defined at dibp %p\n", i<<8, dib_unit[i<<8]); } } else { -// printf("Chan_set_dev Channel %04x defined at dibp %p\n", i<<8, dib_chan[i]); +//printf("Chan_set_dev Channel %04x defined at dibp %p\n", i<<8, dib_chan[i]); /* channel is defined, see if defined in dib_unit array */ if ((dib_unit[i<<8]) == 0) { /* write dibp to units array */ @@ -2767,49 +2591,58 @@ t_stat set_dev_addr(UNIT *uptr, int32 val, CONST char *cptr, void *desc) { int i; /* temp */ int chsa, ochsa; /* dev addr */ -// fprintf(stderr, "Set dev entry DEVICE ptr %s\r\n", cptr); if (cptr == NULL) /* is there a UNIT name specified */ return SCPE_ARG; /* no, arg error */ if (uptr == NULL) /* is there a UNIT pointer */ return SCPE_IERR; /* no, arg error */ dptr = get_dev(uptr); /* find the device from unit pointer */ if (dptr == NULL) { /* device not found, so error */ - fprintf(stderr, "Set dev no DEVICE ptr %s\r\n", cptr); + fprintf(stderr, "Set dev no DEVICE cptr %s\r\n", cptr); +//printf("Set dev no DEVICE ptr %s\r\n", cptr); return SCPE_IERR; /* error */ } +//printf("Set dev DEVICE ptr %s\r\n", cptr); dibp = (DIB *)dptr->ctxt; /* get dib pointer from device struct */ if (dibp == NULL) { /* we need a DIB */ fprintf(stderr, "Set dev no DIB ptr %s\r\n", cptr); +//printf("Set dev no DIB ptr %s\r\n", cptr); return SCPE_IERR; /* no DIB, so error */ } -// fprintf(stderr, "Set dev new addr %s\r\n", cptr); chan = get_uint(cptr, 16, 0xffff, &r); /* get new device address */ if (r != SCPE_OK) /* need good number */ return r; /* number error, return error */ - chan &= 0x7f00; /* clean channel address */ +//printf("Set new dev DEVICE ptr %s chan %04x\r\n", cptr, chan); +//ZZchan &= 0x7f00; /* clean channel address */ dibp->chan_addr = chan; /* set new parent channel addr */ -// fprintf(stderr, "Set dev new addr %s chan %02x\r\n", cptr, chan); /* change all the unit addresses with the new channel, but keep sub address */ /* Clear out existing entries for all units on this device */ tuptr = dptr->units; /* get pointer to units defined for this device */ -// fprintf(stderr, "Set dev new addr %s chan %04X units %02X\r\n", cptr, chan, dibp->numunits); /* loop through all units for this device */ for (i = 0; i < dibp->numunits; i++) { ochsa = GET_UADDR(tuptr->u3); /* get old chsa for this unit */ +//printf("Got old chsa %04x\r\n", ochsa); dib_unit[ochsa] = NULL; /* clear sa dib pointer */ dib_unit[ochsa&0x7f00] = NULL; /* clear the channel dib address */ - chsa = chan | (ochsa & 0xff); /* merge new channel with old sa */ + if (dptr->flags & DEV_CHAN) { /* Is this a channel device IOP/MFP */ + chan &= 0x7ff0; /* clean channel sub-address */ + chsa = chan | (ochsa & 0xf); /* merge new channel with old sa */ + } else { + chan &= 0x7f00; /* clean channel address */ + chsa = chan | (ochsa & 0xff); /* merge new channel with old sa */ + } + if (chsa != ochsa) { + fprintf(stderr, "Set new chsa %04x old chsa %04x\r\n", chsa, ochsa); +//printf("Set new chsa %04x old chsa %04x\r\n", chsa, ochsa); + } tuptr->u3 &= ~UNIT_ADDR_MASK; /* clear old chsa for this unit */ tuptr->u3 |= UNIT_ADDR(chsa); /* set new chsa for this unit */ dib_unit[chan&0x7f00] = dibp; /* set the channel dib address */ dib_unit[chsa] = dibp; /* save the dib address for new chsa */ -// fprintf(stderr, "Set old chsa %04X to new addr %04X new chsa %04X\r\n", -// ochsa, GET_UADDR(tuptr->u3), chsa); tuptr++; /* next unit pointer */ } return SCPE_OK; diff --git a/SEL32/sel32_clk.c b/SEL32/sel32_clk.c index 6f492ba..9425da6 100644 --- a/SEL32/sel32_clk.c +++ b/SEL32/sel32_clk.c @@ -268,6 +268,8 @@ DEVICE itm_dev = { 1, 8, 8, 1, 8, 8, NULL, NULL, &itm_reset, /* examine, deposit, reset */ NULL, NULL, NULL, /* boot, attach, detach */ + /* dib, dev flags, debug flags, debug */ +// NULL, DEV_DEBUG|DEV_DIS|DEV_DISABLE, 0, dev_debug, NULL, DEV_DEBUG, 0, dev_debug, /* dib, dev flags, debug flags, debug */ NULL, NULL, &itm_help, /* ?, ?, help */ NULL, NULL, &itm_desc, /* ?, ?, description */ @@ -403,8 +405,14 @@ int32 itm_rdwr(uint32 cmd, int32 cnt, uint32 level) sim_activate_after_abs_d(&itm_unit, ((double)cnt*1000000)/rtc_tps); else /* use interval timer freq */ -//MPX3X sim_activate_after_abs_d(&itm_unit, ((double)cnt*itm_tick_size_x_100)/100.0); - sim_activate_after_abs_d(&itm_unit, ((double)(cnt+1)*itm_tick_size_x_100)/100.0); +#ifdef MAYBE_CHANGE_FOR_MPX3X + /* this fixes an extra interrupt being generated on context switch */ + /* the value is load for the new task anyway */ + /* need to verify that UTX likes it too */ +/*4MPX3X*/ sim_activate_after_abs_d(&itm_unit, ((double)(cnt+1)*itm_tick_size_x_100)/100.0); +#else + sim_activate_after_abs_d(&itm_unit, ((double)cnt*itm_tick_size_x_100)/100.0); +#endif itm_run = 1; /* set timer running */ } sim_debug(DEBUG_CMD, &itm_dev, @@ -579,7 +587,7 @@ int32 itm_rdwr(uint32 cmd, int32 cnt, uint32 level) /* get simulated negative start time in counts */ temp = temp - itm_strt; /* make into a negative number */ } -// sim_cancel (&itm_unit); /* cancel timer */ +//extra sim_cancel (&itm_unit); /* cancel timer */ } sim_debug(DEBUG_CMD, &itm_dev, "Intv 0x%02x temp value %08x (%08d)\n", cmd, temp, temp); diff --git a/SEL32/sel32_com.c b/SEL32/sel32_com.c index 3494c41..28e8165 100644 --- a/SEL32/sel32_com.c +++ b/SEL32/sel32_com.c @@ -184,6 +184,8 @@ TMXR com_desc = { COM_LINES_DFLT, 0, 0, com_ldsc }; /* com descr */ /* u6 */ +/* forward definitions */ +uint16 com_preio(UNIT *uptr, uint16 chan); uint16 com_startcmd(UNIT *uptr, uint16 chan, uint8 cmd); uint16 com_haltio(UNIT *uptr); void com_ini(UNIT *, t_bool); @@ -197,7 +199,7 @@ t_stat com_reset(DEVICE *dptr); t_stat com_attach(UNIT *uptr, CONST char *cptr); t_stat com_detach(UNIT *uptr); void com_reset_ln(int32 ln); -const char *com_description(DEVICE *dptr); /* device description */ +const char *com_description(DEVICE *dptr); /* device description */ /* COM data structures com_chp COM channel program information @@ -239,10 +241,8 @@ UNIT com_unit[] = { {UDATA(&comi_srv, UNIT_ATTABLE|UNIT_IDLE, 0), COM_WAIT, UNIT_ADDR(0x0000)}, /* 0 */ }; -//DIB com_dib = {NULL, com_startcmd, NULL, NULL, com_ini, com_unit, com_chp, COM_UNITS, 0x0f, 0x7e00, 0, 0, 0}; - DIB com_dib = { - NULL, /* uint16 (*pre_io)(UNIT *uptr, uint16 chan)*/ /* Pre Start I/O */ + com_preio, /* uint16 (*pre_io)(UNIT *uptr, uint16 chan)*/ /* Pre Start I/O */ com_startcmd, /* uint16 (*start_cmd)(UNIT *uptr, uint16 chan, uint8 cmd)*/ /* Start command */ NULL, /* uint16 (*halt_io)(UNIT *uptr) */ /* Halt I/O */ NULL, /* uint16 (*stop_io)(UNIT *uptr) */ /* Stop I/O */ @@ -298,26 +298,24 @@ CHANP coml_chp[COM_LINES*2] = {0}; UNIT coml_unit[] = { /* 0-7 is input, 8-f is output */ - {UDATA(&como_srv, TT_MODE_UC|UNIT_COML, 0), COML_WAIT, UNIT_ADDR(0x7EC0)}, /* 0 */ - {UDATA(&como_srv, TT_MODE_UC|UNIT_COML, 0), COML_WAIT, UNIT_ADDR(0x7EC1)}, /* 1 */ - {UDATA(&como_srv, TT_MODE_UC|UNIT_COML, 0), COML_WAIT, UNIT_ADDR(0x7EC2)}, /* 2 */ - {UDATA(&como_srv, TT_MODE_UC|UNIT_COML, 0), COML_WAIT, UNIT_ADDR(0x7EC3)}, /* 3 */ - {UDATA(&como_srv, TT_MODE_UC|UNIT_COML, 0), COML_WAIT, UNIT_ADDR(0x7EC4)}, /* 4 */ - {UDATA(&como_srv, TT_MODE_UC|UNIT_COML, 0), COML_WAIT, UNIT_ADDR(0x7EC5)}, /* 5 */ - {UDATA(&como_srv, TT_MODE_UC|UNIT_COML, 0), COML_WAIT, UNIT_ADDR(0x7EC6)}, /* 6 */ - {UDATA(&como_srv, TT_MODE_UC|UNIT_COML, 0), COML_WAIT, UNIT_ADDR(0x7EC7)}, /* 7 */ - {UDATA(&como_srv, TT_MODE_UC|UNIT_COML, 0), COML_WAIT, UNIT_ADDR(0x7EC8)}, /* 8 */ - {UDATA(&como_srv, TT_MODE_UC|UNIT_COML, 0), COML_WAIT, UNIT_ADDR(0x7EC9)}, /* 9 */ - {UDATA(&como_srv, TT_MODE_UC|UNIT_COML, 0), COML_WAIT, UNIT_ADDR(0x7ECA)}, /* A */ - {UDATA(&como_srv, TT_MODE_UC|UNIT_COML, 0), COML_WAIT, UNIT_ADDR(0x7ECB)}, /* B */ - {UDATA(&como_srv, TT_MODE_UC|UNIT_COML, 0), COML_WAIT, UNIT_ADDR(0x7ECC)}, /* C */ - {UDATA(&como_srv, TT_MODE_UC|UNIT_COML, 0), COML_WAIT, UNIT_ADDR(0x7ECD)}, /* D */ - {UDATA(&como_srv, TT_MODE_UC|UNIT_COML, 0), COML_WAIT, UNIT_ADDR(0x7ECE)}, /* E */ - {UDATA(&como_srv, TT_MODE_UC|UNIT_COML, 0), COML_WAIT, UNIT_ADDR(0x7ECF)}, /* F */ + {UDATA(&como_srv, TT_MODE_UC|UNIT_COML, 0), COML_WAIT, UNIT_ADDR(0x7EC0)}, /* 0 */ + {UDATA(&como_srv, TT_MODE_UC|UNIT_COML, 0), COML_WAIT, UNIT_ADDR(0x7EC1)}, /* 1 */ + {UDATA(&como_srv, TT_MODE_UC|UNIT_COML, 0), COML_WAIT, UNIT_ADDR(0x7EC2)}, /* 2 */ + {UDATA(&como_srv, TT_MODE_UC|UNIT_COML, 0), COML_WAIT, UNIT_ADDR(0x7EC3)}, /* 3 */ + {UDATA(&como_srv, TT_MODE_UC|UNIT_COML, 0), COML_WAIT, UNIT_ADDR(0x7EC4)}, /* 4 */ + {UDATA(&como_srv, TT_MODE_UC|UNIT_COML, 0), COML_WAIT, UNIT_ADDR(0x7EC5)}, /* 5 */ + {UDATA(&como_srv, TT_MODE_UC|UNIT_COML, 0), COML_WAIT, UNIT_ADDR(0x7EC6)}, /* 6 */ + {UDATA(&como_srv, TT_MODE_UC|UNIT_COML, 0), COML_WAIT, UNIT_ADDR(0x7EC7)}, /* 7 */ + {UDATA(&como_srv, TT_MODE_UC|UNIT_COML, 0), COML_WAIT, UNIT_ADDR(0x7EC8)}, /* 8 */ + {UDATA(&como_srv, TT_MODE_UC|UNIT_COML, 0), COML_WAIT, UNIT_ADDR(0x7EC9)}, /* 9 */ + {UDATA(&como_srv, TT_MODE_UC|UNIT_COML, 0), COML_WAIT, UNIT_ADDR(0x7ECA)}, /* A */ + {UDATA(&como_srv, TT_MODE_UC|UNIT_COML, 0), COML_WAIT, UNIT_ADDR(0x7ECB)}, /* B */ + {UDATA(&como_srv, TT_MODE_UC|UNIT_COML, 0), COML_WAIT, UNIT_ADDR(0x7ECC)}, /* C */ + {UDATA(&como_srv, TT_MODE_UC|UNIT_COML, 0), COML_WAIT, UNIT_ADDR(0x7ECD)}, /* D */ + {UDATA(&como_srv, TT_MODE_UC|UNIT_COML, 0), COML_WAIT, UNIT_ADDR(0x7ECE)}, /* E */ + {UDATA(&como_srv, TT_MODE_UC|UNIT_COML, 0), COML_WAIT, UNIT_ADDR(0x7ECF)}, /* F */ }; -//DIB coml_dib = { NULL, com_startcmd, NULL, NULL, NULL, coml_ini, -//coml_unit, coml_chp, COM_LINES*2, 0x0f, 0x7E00}; DIB coml_dib = { NULL, /* uint16 (*pre_io)(UNIT *uptr, uint16 chan)*/ /* Pre Start I/O */ com_startcmd, /* uint16 (*start_cmd)(UNIT *uptr, uint16 chan, uint8 cmd)*/ /* Start command */ @@ -342,6 +340,7 @@ REG coml_reg[] = { }; MTAB coml_mod[] = { + {MTAB_XTD | MTAB_VUN | MTAB_VALR, 0, "DEV", "DEV", &set_dev_addr, &show_dev_addr, NULL}, { TT_MODE, TT_MODE_UC, "UC", "UC", NULL }, { TT_MODE, TT_MODE_7B, "7b", "7B", NULL }, { TT_MODE, TT_MODE_8B, "8b", "8B", NULL }, @@ -392,7 +391,8 @@ void com_ini(UNIT *uptr, t_bool f) { DEVICE *dptr = get_dev(uptr); - sim_debug(DEBUG_CMD, dptr, "COM init device %s controller 0x7e00\n", dptr->name); + sim_debug(DEBUG_CMD, dptr, + "COM init device %s controller 0x7e00\n", dptr->name); sim_cancel(uptr); /* stop input poll */ sim_activate(uptr, 1000); /* start input poll */ } @@ -409,6 +409,27 @@ uint16 com_rschnlio(UNIT *uptr) { return SCPE_OK; } +/* start a com operation */ +uint16 com_preio(UNIT *uptr, uint16 chan) { + DEVICE *dptr = get_dev(uptr); + int unit = (uptr - dptr->units); + uint16 chsa = GET_UADDR(uptr->u3); /* get channel/sub-addr */ +// int cmd = uptr->u3 & 0xff; + +#ifdef WAIT_FOR_TESTING + sim_debug(DEBUG_CMD, dptr, "com_preio CMD %08x unit %02x chsa %04x\n", + uptr->u3, unit, chsa); + if ((uptr->u3 & COM_MSK) != 0) { /* just return if busy */ + sim_debug(DEBUG_CMD, dptr, + "com_preio unit %02x chsa %04x BUSY\n", unit, chsa); + return SNS_BSY; + } +#endif + + sim_debug(DEBUG_CMD, dptr, "t_preio unit %02x chsa %04xOK\n", unit, chsa); + return SCPE_OK; /* good to go */ +} + /* called from sel32_chan to start an I/O operation */ uint16 com_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) { @@ -420,7 +441,8 @@ uint16 com_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) return SNS_BSY; /* yes, return busy */ } - sim_debug(DEBUG_CMD, dptr, "CMD unit %04x chan %04x cmd %02x\n", unit, chan, cmd); + sim_debug(DEBUG_CMD, dptr, + "CMD unit %04x chan %04x cmd %02x\n", unit, chan, cmd); /* process the commands */ switch (cmd & 0xFF) { @@ -436,7 +458,8 @@ uint16 com_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) case COM_WR: /* 0x01 */ /* Write command */ case COM_WRSCM: /* 0x05 */ /* Write w/sub channel monitor */ case COM_WRHFC: /* 0x0D */ /* Write w/hardware flow control */ - sim_debug(DEBUG_CMD, dptr, "com_startcmd %04x: Cmd WRITE %02x\n", chan, cmd); + sim_debug(DEBUG_CMD, dptr, + "com_startcmd %04x: Cmd WRITE %02x\n", chan, cmd); uptr->u3 &= LMASK; /* leave only chsa */ uptr->u3 |= (cmd & COM_MSK); /* save command */ @@ -466,12 +489,14 @@ uint16 com_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) uptr->u3 |= COM_READ; /* show read mode */ uptr->u5 = SNS_RDY|SNS_ONLN; /* status is online & ready */ sim_debug(DEBUG_CMD, dptr, - "com_startcmd %04x: input cnt = %04x\n", chan, coml_chp[unit].ccw_count); + "com_startcmd %04x: input cnt = %04x\n", + chan, coml_chp[unit].ccw_count); return 0; break; case COM_NOP: /* 0x03 */ /* NOP has do nothing */ - sim_debug(DEBUG_CMD, dptr, "com_startcmd %04x: Cmd %02x NOP\n", chan, cmd); + sim_debug(DEBUG_CMD, dptr, + "com_startcmd %04x: Cmd %02x NOP\n", chan, cmd); uptr->u5 = SNS_RDY|SNS_ONLN; /* status is online & ready */ uptr->u3 &= LMASK; /* leave only chsa */ uptr->u3 |= (cmd & COM_MSK); /* save command */ @@ -484,7 +509,8 @@ uint16 com_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) /* value 4 is Data Set Ready */ /* value 5 is Data carrier detected n/u */ sim_debug(DEBUG_CMD, dptr, - "com_startcmd %04x: unit %04x Cmd Sense %02x\n", chan, unit, uptr->u5); + "com_startcmd %04x: unit %04x Cmd Sense %02x\n", + chan, unit, uptr->u5); ch = (com_lstat[unit][0] >> 24) & 0xff; chan_write_byte(GET_UADDR(uptr->u3), &ch); /* write status */ @@ -522,7 +548,8 @@ uint16 com_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) break; case COM_DEFSC: /* 0x0B */ /* Define special char */ - sim_debug(DEBUG_CMD, dptr, "com_startcmd %04x: Cmd %02x DEFSC\n", chan, cmd); + sim_debug(DEBUG_CMD, dptr, + "com_startcmd %04x: Cmd %02x DEFSC\n", chan, cmd); if (chan_read_byte(GET_UADDR(uptr->u3), &ch)) { /* read char from memory */ /* nothing to read, error */ return SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK; /* good return */ @@ -606,8 +633,9 @@ uint16 com_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) #define ACE_WAKE 0x0000FF00 /* 8 bit wake-up character */ #endif - case COM_SACE: /* 0xff */ /* Set ACE parameters (3 chars) */ - sim_debug(DEBUG_CMD, dptr, "com_startcmd %04x: Cmd %02x SACE\n", chan, cmd); + case COM_SACE: /* 0xff */ /* Set ACE parameters (3 chars) */ + sim_debug(DEBUG_CMD, dptr, + "com_startcmd %04x: Cmd %02x SACE\n", chan, cmd); if (chan_read_byte(GET_UADDR(uptr->u3), &ch)) { /* read char 0 */ /* nothing to read, error */ return SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK; /* good return */ @@ -623,7 +651,8 @@ uint16 com_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) return SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK; /* good return */ } uptr->u4 |= ((uint32)ch)<<8; /* byte 2 of ACE data */ - sim_debug(DEBUG_CMD, dptr, "com_startcmd %04x: Cmd %02x ACE bytes %08x\n", + sim_debug(DEBUG_CMD, dptr, + "com_startcmd %04x: Cmd %02x ACE bytes %08x\n", chan, cmd, uptr->u4); return SNS_CHNEND|SNS_DEVEND; /* good return */ break; @@ -631,7 +660,8 @@ uint16 com_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) default: /* invalid command */ uptr->u5 |= SNS_CMDREJ; /* command rejected */ - sim_debug(DEBUG_CMD, dptr, "com_startcmd %04x: Cmd Invald %02x status %02x\n", + sim_debug(DEBUG_CMD, dptr, + "com_startcmd %04x: Cmd Invald %02x status %02x\n", chan, cmd, uptr->u5); return SNS_CHNEND|STATUS_PCHK; /* program check */ break; @@ -656,10 +686,12 @@ t_stat comi_srv(UNIT *uptr) ln = uptr - com_unit; /* line # */ /* handle NOP and INCH cmds */ - sim_debug(DEBUG_CMD, dptr, "comi_srv entry chsa %04x line %02x cmd %02x\n", chsa, ln, cmd); + sim_debug(DEBUG_CMD, dptr, + "comi_srv entry chsa %04x line %02x cmd %02x\n", chsa, ln, cmd); if (cmd == COM_NOP || cmd == 0x7f) { /* check for NOP or INCH */ uptr->u3 &= LMASK; /* leave only chsa */ - sim_debug(DEBUG_CMD, dptr, "comi_srv NOP or INCH done chsa %04x line %02x cmd %02x\n", + sim_debug(DEBUG_CMD, dptr, + "comi_srv NOP or INCH done chsa %04x line %02x cmd %02x\n", chsa, ln, cmd); chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* done */ return SCPE_OK; /* return */ @@ -729,7 +761,8 @@ t_stat comi_srv(UNIT *uptr) if (((comlp->u4 & ACE_WAKE) >> 8) == ch) { /* send attention to OS here for this channel */ /* need to get chsa here for the channel */ - set_devwake(chsa, SNS_ATTN|SNS_DEVEND|SNS_CHNEND); /* tell user */ + /* tell user */ + set_devwake(chsa, SNS_ATTN|SNS_DEVEND|SNS_CHNEND); } } } /* end else char */ @@ -752,10 +785,12 @@ t_stat como_srv(UNIT *uptr) uint8 ch; /* handle NOP and INCH cmds */ - sim_debug(DEBUG_CMD, dptr, "como_srv entry chsa %04x line %04x cmd %02x\n", chsa, ln, cmd); + sim_debug(DEBUG_CMD, dptr, + "como_srv entry chsa %04x line %04x cmd %02x\n", chsa, ln, cmd); if (cmd == COM_NOP || cmd == 0x7f) { /* check for NOP or INCH */ uptr->u3 &= LMASK; /* leave only chsa */ - sim_debug(DEBUG_CMD, &com_dev, "como_srv NOP or INCH done chsa %04x line %04x cmd %02x\n", + sim_debug(DEBUG_CMD, &com_dev, + "como_srv NOP or INCH done chsa %04x line %04x cmd %02x\n", chsa, ln, cmd); chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* done */ return SCPE_OK; /* return */ @@ -771,7 +806,8 @@ t_stat como_srv(UNIT *uptr) return SCPE_OK; /* return */ } - sim_debug(DEBUG_CMD, dptr, "como_srv entry 1 chsa %04x line %04x cmd %02x\n", chsa, ln, cmd); + sim_debug(DEBUG_CMD, dptr, + "como_srv entry 1 chsa %04x line %04x cmd %02x\n", chsa, ln, cmd); if (cmd) { /* get a user byte from memory */ done = chan_read_byte(chsa, &ch); /* get byte from memory */ @@ -781,28 +817,33 @@ t_stat como_srv(UNIT *uptr) return SCPE_OK; if (com_dev.flags & DEV_DIS) { /* disabled */ - sim_debug(DEBUG_CMD, dptr, "como_srv chsa %04x line %04x DEV_DIS set\n", chsa, ln); + sim_debug(DEBUG_CMD, dptr, + "como_srv chsa %04x line %04x DEV_DIS set\n", chsa, ln); if (done) { - sim_debug(DEBUG_CMD, dptr, "como_srv Write DONE %04x status %04x\n", + sim_debug(DEBUG_CMD, dptr, + "como_srv Write DONE %04x status %04x\n", ln, SNS_CHNEND|SNS_DEVEND); chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* done */ } return SCPE_OK; /* return */ } - sim_debug(DEBUG_CMD, dptr, "como_srv poll chsa %04x line %04x DEV_DIS set\n", chsa, ln); + sim_debug(DEBUG_CMD, dptr, + "como_srv poll chsa %04x line %04x DEV_DIS set\n", chsa, ln); if (com_ldsc[ln].conn) { /* connected? */ if (com_ldsc[ln].xmte) { /* xmt enabled? */ if (done) { /* are we done writing */ endit: uptr->u3 &= LMASK; /* nothing left, command complete */ - sim_debug(DEBUG_CMD, dptr, "com_srvo write %04x: chnend|devend\n", ln); + sim_debug(DEBUG_CMD, dptr, + "com_srvo write %04x: chnend|devend\n", ln); chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* done */ return SCPE_OK; } /* send the next char out */ tmxr_putc_ln(&com_ldsc[ln], ch); /* output char */ - sim_debug(DEBUG_CMD, dptr, "com_srvo writing char 0x%02x to ln %04x\n", ch, ln); + sim_debug(DEBUG_CMD, dptr, + "com_srvo writing char 0x%02x to ln %04x\n", ch, ln); tmxr_poll_tx(&com_desc); /* poll xmt */ sim_activate(uptr, uptr->wait); /* wait */ return SCPE_OK; @@ -810,7 +851,8 @@ endit: if (done) /* are we done writing */ goto endit; /* done */ /* just dump the char */ - sim_debug(DEBUG_CMD, dptr, "com_srvo write dumping char 0x%02x on line %04x\n", ch, ln); + sim_debug(DEBUG_CMD, dptr, + "com_srvo write dumping char 0x%02x on line %04x\n", ch, ln); tmxr_poll_tx(&com_desc); /* poll xmt */ sim_activate(uptr, uptr->wait); /* wait */ return SCPE_OK; @@ -818,7 +860,8 @@ endit: } else { /* not connected, so dump char on ground */ if (done) { - sim_debug(DEBUG_CMD, dptr, "com_srvo write dump DONE line %04x status %04x\n", + sim_debug(DEBUG_CMD, dptr, + "com_srvo write dump DONE line %04x status %04x\n", ln, SNS_CHNEND|SNS_DEVEND); uptr->u3 &= LMASK; /* nothing left, command complete */ chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* done */ @@ -885,7 +928,7 @@ void com_reset_ln (int32 ln) t_stat com_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr) { -fprintf (st, "SEL32 8-Line Async Controller Terminal Interfaces\n\n"); +fprintf (st, "SEL32 8512 8-Line Async Controller Terminal Interfaces\n\n"); fprintf (st, "Terminals perform input and output through Telnet sessions connected to a \n"); fprintf (st, "user-specified port.\n\n"); fprintf (st, "The ATTACH command specifies the port to be used:\n\n"); @@ -926,7 +969,7 @@ fprintf (st, "are lost when the simulator shuts down or DCI is detached.\n"); /* description of controller */ const char *com_description (DEVICE *dptr) { - return "SEL 32 8-Line async communications controller"; + return "SEL-32 8512 8-Line async communications controller"; } #endif diff --git a/SEL32/sel32_con.c b/SEL32/sel32_con.c index 504c0cd..e3ee7fc 100644 --- a/SEL32/sel32_con.c +++ b/SEL32/sel32_con.c @@ -117,10 +117,8 @@ UNIT con_unit[] = { {UDATA(&con_srvo, UNIT_CON, 0), 0, UNIT_ADDR(0x7EFD)}, /* Output */ }; -//DIB con_dib = {NULL,con_startcmd,NULL,NULL,NULL,con_ini, -//con_unit,con_chp,NUM_UNITS_CON,0xf,0x7e00,0,0,0}; DIB con_dib = { - con_preio, /* uint16 (*pre_io)(UNIT *uptr, uint16 chan)*/ /* Start I/O */ + con_preio, /* uint16 (*pre_io)(UNIT *uptr, uint16 chan)*/ /* Pre Start I/O */ con_startcmd, /* uint16 (*start_cmd)(UNIT *uptr, uint16 chan, uint8 cmd)*/ /* Start command */ con_haltio, /* uint16 (*halt_io)(UNIT *uptr) */ /* Halt I/O */ NULL, /* uint16 (*stop_io)(UNIT *uptr) */ /* Stop I/O */ @@ -535,8 +533,10 @@ t_stat con_srvi(UNIT *uptr) { atbuf = (ch)<<8; /* start anew */ uptr->CMD |= CON_ATAT; /* show getting @ */ } +#ifndef TEST4MPX if (ch == '\n') /* convert newline */ ch = '\r'; /* make newline into carriage return */ +#endif sim_debug(DEBUG_CMD, &con_dev, "con_srvi handle readch unit %02x: CMD %08x read %02x u4 %02x incnt %02x r %x\n", unit, uptr->CMD, ch, uptr->u4, con_data[unit].incnt, r); diff --git a/SEL32/sel32_cpu.c b/SEL32/sel32_cpu.c index c35f1bf..5cbe6d9 100644 --- a/SEL32/sel32_cpu.c +++ b/SEL32/sel32_cpu.c @@ -24,8 +24,6 @@ #include "sel32_defs.h" -#define DO_DYNAMIC_DEBUG - /* Concept 32 PSD Mode Trap/Interrupt Priorities */ /* Relative|Logical |Int Vect|TCW |IOCD|Description */ /* Priority|Priority|Location|Addr|Addr */ @@ -263,8 +261,6 @@ UNIT cpu_unit = 80, /* int32 wait */ /* wait */ }; -//UNIT cpu_unit = { UDATA (&rtc_srv, UNIT_BINK, MAXMEMSIZE) }; - REG cpu_reg[] = { {HRDATAD(PC, PC, 24, "Program Counter"), REG_FIT}, {BRDATAD(PSD, PSD, 16, 32, 2, "Program Status Doubleword"), REG_FIT}, @@ -301,14 +297,14 @@ MTAB cpu_mod[] = { { /* MTAB table layout for cpu type */ /* {UNIT_MODEL, MODEL(MODEL_55), "32/55", "32/55", NULL, NULL, NULL, "Concept 32/55"}, */ - UNIT_MODEL, /* uint32 mask */ /* mask */ - MODEL(MODEL_55), /* uint32 match */ /* match */ - "32/55", /* cchar *pstring */ /* print string */ - "32/55", /* cchar *mstring */ /* match string */ - NULL, /* t_stat (*valid) */ /* validation routine */ - NULL, /* t_stat (*disp) */ /* display routine */ - NULL, /* void *desc */ /* value descriptor, REG* if MTAB_VAL, int* if not */ - "Concept 32/55", /* cchar *help */ /* help string */ + UNIT_MODEL, /* uint32 mask */ /* mask */ + MODEL(MODEL_55), /* uint32 match */ /* match */ + "32/55", /* cchar *pstring */ /* print string */ + "32/55", /* cchar *mstring */ /* match string */ + NULL, /* t_stat (*valid) */ /* validation routine */ + NULL, /* t_stat (*disp) */ /* display routine */ + NULL, /* void *desc */ /* value desc, REG* if MTAB_VAL, int* if not */ + "Concept 32/55", /* cchar *help */ /* help string */ }, {UNIT_MODEL, MODEL(MODEL_75), "32/75", "32/75", NULL, NULL, NULL, "Concept 32/75"}, {UNIT_MODEL, MODEL(MODEL_27), "32/27", "32/27", NULL, NULL, NULL, "Concept 32/27"}, @@ -320,14 +316,14 @@ MTAB cpu_mod[] = { { /* MTAB table layout for cpu memory size */ /* {UNIT_MSIZE, MEMAMOUNT(0), "128K", "128K", &cpu_set_size}, */ - UNIT_MSIZE, /* uint32 mask */ /* mask */ - MEMAMOUNT(0), /* uint32 match */ /* match */ - NULL, /* cchar *pstring */ /* print string */ - "128K", /* cchar *mstring */ /* match string */ - &cpu_set_size, /* t_stat (*valid) */ /* validation routine */ - NULL, /* t_stat (*disp) */ /* display routine */ - NULL, /* void *desc */ /* value descriptor, REG* if MTAB_VAL, int* if not */ - NULL, /* cchar *help */ /* help string */ + UNIT_MSIZE, /* uint32 mask */ /* mask */ + MEMAMOUNT(0), /* uint32 match */ /* match */ + NULL, /* cchar *pstring */ /* print string */ + "128K", /* cchar *mstring */ /* match string */ + &cpu_set_size, /* t_stat (*valid) */ /* validation routine */ + NULL, /* t_stat (*disp) */ /* display routine */ + NULL, /* void *desc */ /* value desc, REG* if MTAB_VAL, int* if not */ + NULL, /* cchar *help */ /* help string */ }, {UNIT_MSIZE, MEMAMOUNT(1), NULL, "256K", &cpu_set_size}, {UNIT_MSIZE, MEMAMOUNT(2), NULL, "512K", &cpu_set_size}, @@ -353,33 +349,33 @@ DEVICE cpu_dev = { &cpu_ex, &cpu_dep, &cpu_reset, NULL, NULL, NULL, NULL, DEV_DEBUG, 0, dev_debug, NULL, NULL, &cpu_help, NULL, NULL, &cpu_description */ - "CPU", /* cchar *name */ /* device name */ - &cpu_unit, /* UNIT *units */ /* unit array */ - cpu_reg, /* REG *registers */ /* register array */ - cpu_mod, /* MTAB *modifiers */ /* modifier array */ - 1, /* uint32 numunits */ /* number of units */ - 16, /* uint32 aradix */ /* address radix */ - 32, /* uint32 awidth */ /* address width */ - 1, /* uint32 aincr */ /* address increment */ - 16, /* uint32 dradix */ /* data radix */ - 8, /* uint32 dwidth */ /* data width */ - &cpu_ex, /* t_stat (*examine) */ /* examine routine */ - &cpu_dep, /* t_stat (*deposit) */ /* deposit routine */ - &cpu_reset, /* t_stat (*reset) */ /* reset routine */ - NULL, /* t_stat (*boot) */ /* boot routine */ - NULL, /* t_stat (*attach) */ /* attach routine */ - NULL, /* t_stat (*detach) */ /* detach routine */ - NULL, /* void *ctxt */ /* (context) device information block pointer */ - DEV_DEBUG, /* uint32 flags */ /* device flags */ - 0, /* uint32 dctrl */ /* debug control flags */ - dev_debug, /* DEBTAB *debflags */ /* debug flag name array */ - NULL, /* t_stat (*msize) */ /* memory size change routine */ - NULL, /* char *lname */ /* logical device name */ - &cpu_help, /* t_stat (*help) */ /* help function */ - NULL, /* t_stat (*attach_help) */ /* attach help function */ - NULL, /* void *help_ctx */ /* Context available to help routines */ - &cpu_description, /* cchar *(*description) */ /* Device description */ - NULL, /* BRKTYPTB *brk_types */ /* Breakpoint types */ + "CPU", /* cchar *name */ /* device name */ + &cpu_unit, /* UNIT *units */ /* unit array */ + cpu_reg, /* REG *registers */ /* register array */ + cpu_mod, /* MTAB *modifiers */ /* modifier array */ + 1, /* uint32 numunits */ /* number of units */ + 16, /* uint32 aradix */ /* address radix */ + 32, /* uint32 awidth */ /* address width */ + 1, /* uint32 aincr */ /* address increment */ + 16, /* uint32 dradix */ /* data radix */ + 8, /* uint32 dwidth */ /* data width */ + &cpu_ex, /* t_stat (*examine) */ /* examine routine */ + &cpu_dep, /* t_stat (*deposit) */ /* deposit routine */ + &cpu_reset, /* t_stat (*reset) */ /* reset routine */ + NULL, /* t_stat (*boot) */ /* boot routine */ + NULL, /* t_stat (*attach) */ /* attach routine */ + NULL, /* t_stat (*detach) */ /* detach routine */ + NULL, /* void *ctxt */ /* (context) device information block pointer */ + DEV_DEBUG, /* uint32 flags */ /* device flags */ + 0, /* uint32 dctrl */ /* debug control flags */ + dev_debug, /* DEBTAB *debflags */ /* debug flag name array */ + NULL, /* t_stat (*msize) */ /* memory size change routine */ + NULL, /* char *lname */ /* logical device name */ + &cpu_help, /* t_stat (*help) */ /* help function */ + NULL, /* t_stat (*attach_help) *//* attach help function */ + NULL, /* void *help_ctx */ /* Context available to help routines */ + &cpu_description, /* cchar *(*description) *//* Device description */ + NULL, /* BRKTYPTB *brk_types */ /* Breakpoint types */ }; /* CPU Instruction decode flags */ @@ -761,7 +757,7 @@ t_stat load_maps(uint32 thepsd[2], uint32 lmap) for (j = 0; j < spc; j++, num++) { /* loop through the midl's */ uint32 pad = RMW(midl+(j<<1)); /* get page descriptor address */ if (num >= MAXMAP) { -/*97V9*/ TRAPSTATUS |= (BIT16|BIT9); /* set bit 5 of trap status */ + TRAPSTATUS |= (BIT16|BIT9); /* set bit 5 of trap status */ return MAPFLT; /* map loading overflow, map fault error */ } /* load 16 bit map descriptors */ @@ -771,7 +767,7 @@ t_stat load_maps(uint32 thepsd[2], uint32 lmap) } /* if none loaded, map fault */ if (num == 0) { -/*97V9*/ TRAPSTATUS |= (BIT16|BIT9); /* set bit 5 of trap status */ + TRAPSTATUS |= (BIT16|BIT9); /* set bit 5 of trap status */ return MAPFLT; /* attempt to load 0 maps, map fault error */ } /* clear the rest of the previously used maps */ @@ -1012,7 +1008,8 @@ loaduser: /* it is OK here to have no O/S maps loaded, num can be 0 */ if ((spc > MAXMAP) || ((spc+BPIX) > MAXMAP)) { sim_debug(DEBUG_TRAP, &cpu_dev, - "load_maps bad User page count %04x num %04x bpix %04x, map fault\n", spc, num, BPIX); + "load_maps bad User page count %04x num %04x bpix %04x, map fault\n", + spc, num, BPIX); /* Bad map load count specified. */ BPIX = 0; /* no os maps loaded */ CPIXPL = 0; /* no user pages */ @@ -1044,7 +1041,7 @@ loaduser: sim_debug(DEBUG_TRAP, &cpu_dev, "load_maps User page count overflow %04x, map fault\n", num); TRAPSTATUS |= BIT16; /* set bit 16 of trap status */ -/*97&V6*/ TRAPSTATUS |= (BIT5|BIT9); /* set bit 5 of trap status */ + TRAPSTATUS |= (BIT5|BIT9); /* set bit 5 of trap status */ goto nomaps; /* map overflow, map fault trap */ } if (!MEM_ADDR_OK(pad)) { /* see if address is within our memory */ @@ -1217,7 +1214,7 @@ t_stat RealAddr(uint32 addr, uint32 *realaddr, uint32 *prot, uint32 access) if ((MODES & MAPMODE) == 0) { /* we are in unmapped mode, check if valid real address */ - if (!MEM_ADDR_OK(word)) { /* see if address is within our memory */ + if (!MEM_ADDR_OK(word)) { /* see if address is within our memory */ if ((CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9)) { if (access == MEM_RD) TRAPSTATUS |= BIT1; /* set bit 1 of trap status */ @@ -1255,8 +1252,8 @@ t_stat RealAddr(uint32 addr, uint32 *realaddr, uint32 *prot, uint32 access) } else if ((CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9)) { - // V9 & 32/97 wants MACHINECHK for test 37/1 in CN.MMM & VM.MMM */ -/*97&V6*/ TRAPSTATUS |= (BIT7|BIT9); /* set bit 7 of trap status */ + // V9 & 32/97 wants MACHINECHK for test 37/1 in CN.MMM & VM.MMM + TRAPSTATUS |= (BIT7|BIT9); /* set bit 7 of trap status */ TRAPSTATUS |= BIT28; /* set bit 28 of trap status */ return MACHINECHK_TRAP; /* diags want machine check error */ } @@ -1394,38 +1391,38 @@ t_stat RealAddr(uint32 addr, uint32 *realaddr, uint32 *prot, uint32 access) MEMSIZE, mpl, RMW(mpl), RMW(mpl+4), CPIX, RMW(CPIX+mpl), RMW(CPIX+mpl+4)); /* check user msdl address now that we are going to access it */ - msdl = RMW(mpl+CPIX+4); /* get msdl entry for given CPIX */ - if (!MEM_ADDR_OK(msdl & MASK24)) { /* check user midl */ + msdl = RMW(mpl+CPIX+4); /* get msdl entry for given CPIX */ + if (!MEM_ADDR_OK(msdl & MASK24)) { /* check user midl */ sim_debug(DEBUG_TRAP, &cpu_dev, "RealAddr User CPIX Non Present Memory User msdl %06x CPIX %04x\n", msdl, CPIX); if (CPU_MODEL == MODEL_67) { /* test 37/0 wants MAPFLT trap for 67 */ - TRAPSTATUS |= BIT28; /* set bit 28 of trap status */ - return MAPFLT; /* map fault error on memory access */ + TRAPSTATUS |= BIT28; /* set bit 28 of trap status */ + return MAPFLT; /* map fault error on memory access */ } else if (CPU_MODEL == MODEL_97) { // 32/97 wants MAPFLT for test 37/1 in CN.MMM - TRAPSTATUS |= BIT12; /* set bit 12 of trap status */ -/*97&V6*/ TRAPSTATUS |= (BIT7|BIT9); /* set bit 7/9 of trap status */ -/*97&V9*/ TRAPSTATUS |= BIT10; /* set bit 10 of trap status */ - return MAPFLT; /* no, map fault error */ + TRAPSTATUS |= BIT12; /* set bit 12 of trap status */ + TRAPSTATUS |= (BIT7|BIT9); /* set bit 7/9 of trap status */ + TRAPSTATUS |= BIT10; /* set bit 10 of trap status */ + return MAPFLT; /* no, map fault error */ } else if (CPU_MODEL == MODEL_V6) { // V6 wants MAPFLT for test 37/1 in CN.MMM & VM.MMM */ - TRAPSTATUS |= BIT28; /* set bit 28 of trap status */ + TRAPSTATUS |= BIT28; /* set bit 28 of trap status */ /* OK for V6 */ - return MAPFLT; /* map fault error */ + return MAPFLT; /* map fault error */ } else if (CPU_MODEL == MODEL_V9) { /* V9 wants MAPFLT for test 37/1 in CN.MMM & VM.MMM */ /* V9 fails test 46/subtest 2 with "did not get expected map trap */ - TRAPSTATUS |= BIT12; /* set bit 12 of trap status */ -/*97&V6*/ TRAPSTATUS |= (BIT7|BIT9); /* set bit 7 of trap status */ -/* 97V9*/ TRAPSTATUS |= BIT10; /* set bit 10 of trap status */ - return MAPFLT; /* map fault error */ + TRAPSTATUS |= BIT12; /* set bit 12 of trap status */ + TRAPSTATUS |= (BIT7|BIT9); /* set bit 7 of trap status */ + TRAPSTATUS |= BIT10; /* set bit 10 of trap status */ + return MAPFLT; /* map fault error */ } } @@ -1455,13 +1452,11 @@ t_stat RealAddr(uint32 addr, uint32 *realaddr, uint32 *prot, uint32 access) /* for V6 & V9 handle demand paging */ if (CPU_MODEL >= MODEL_V6) { /* map is not valid, so we have map fault */ -// sim_debug(DEBUG_TRAP, &cpu_dev, sim_debug(DEBUG_EXP, &cpu_dev, "AddrMa %06x RealAddr %06x Map0 HIT %04x, TLB[%3x] %08x MAPC[%03x] %08x\n", addr, word, map, nix, TLB[nix], nix/2, MAPC[nix/2]); /* do a demand page request for the required page */ pfault = nix; /* save page number */ -// sim_debug(DEBUG_TRAP, &cpu_dev, sim_debug(DEBUG_EXP, &cpu_dev, "Mem_write Daddr2 %06x page %04x demand page bits set TLB %08x map %04x\n", addr, nix, TLB[nix], map); @@ -1675,7 +1670,7 @@ t_stat Mem_read(uint32 addr, uint32 *data) } if (status == MAPFLT) { if ((CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9)) -/*97V9*/ TRAPSTATUS |= (BIT12|BIT16); /* set bit 12 of trap status */ + TRAPSTATUS |= (BIT12|BIT16); /* set bit 12 of trap status */ else TRAPSTATUS |= BIT10; /* set bit 10 of trap status */ } @@ -1748,7 +1743,7 @@ t_stat Mem_write(uint32 addr, uint32 *data) addr, page, TLB[page], map, prot, MODES); } else { if (prot) { /* check for write protected memory */ - sim_debug(DEBUG_TRAP, &cpu_dev, + sim_debug(DEBUG_EXP, &cpu_dev, "Mem_writeB 32/67 protect error @ %06x prot %02x page %04x\n", addr, prot, page); if (CPU_MODEL == MODEL_97) @@ -1781,7 +1776,7 @@ t_stat Mem_write(uint32 addr, uint32 *data) } if (status == MAPFLT) { if ((CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9)) -/*97V9*/ TRAPSTATUS |= (BIT12|BIT16); /* set bit 12 of trap status */ + TRAPSTATUS |= (BIT12|BIT16); /* set bit 12 of trap status */ else TRAPSTATUS |= BIT10; /* set bit 10 of trap status */ } @@ -1796,87 +1791,89 @@ t_stat Mem_write(uint32 addr, uint32 *data) /* ovr is setting for CC1 */ void set_CCs(uint32 value, int ovr) { - PSD1 &= 0x87FFFFFE; /* clear the old CC's */ + PSD1 &= 0x87FFFFFE; /* clear the old CC's */ if (ovr) - CC = CC1BIT; /* CC1 value */ + CC = CC1BIT; /* CC1 value */ else - CC = 0; /* CC1 off */ + CC = 0; /* CC1 off */ if (value & FSIGN) - CC |= CC3BIT; /* CC3 for neg */ + CC |= CC3BIT; /* CC3 for neg */ else if (value == 0) - CC |= CC4BIT; /* CC4 for zero */ + CC |= CC4BIT; /* CC4 for zero */ else - CC |= CC2BIT; /* CC2 for greater than zero */ - PSD1 |= (CC & 0x78000000); /* update the CC's in the PSD */ + CC |= CC2BIT; /* CC2 for greater than zero */ + PSD1 |= (CC & 0x78000000); /* update the CC's in the PSD */ } /* retain these values across calls to sim_instr */ -uint32 skipinstr = 0; /* Skip test for interrupt on this instruction */ -uint32 drop_nop = 0; /* Set if right hw instruction is a nop */ -uint32 OIR=0; /* Original Instruction register */ -uint32 OPSD1=0; /* Original PSD1 */ -uint32 OPSD2=0; /* Original PSD2 */ -uint32 TPSD[2]; /* Temp PSD */ +uint32 skipinstr = 0; /* Skip test for interrupt on this instruction */ +uint32 drop_nop = 0; /* Set if right hw instruction is a nop */ +uint32 OIR=0; /* Original Instruction register */ +uint32 OPSD1=0; /* Original PSD1 */ +uint32 OPSD2=0; /* Original PSD2 */ +uint32 TPSD[2]; /* Temp PSD */ /* Opcode definitions */ /* called from simulator */ t_stat sim_instr(void) { - t_stat reason = 0; /* reason for stopping */ - t_uint64 dest = 0; /* Holds destination/source register */ - t_uint64 source = 0; /* Holds source or memory data */ - t_uint64 td; /* Temporary */ - t_int64 int64a; /* temp int */ - t_int64 int64b; /* temp int */ - t_int64 int64c; /* temp int */ - uint32 addr; /* Holds address of last access */ - uint32 temp; /* General holding place for stuff */ - uint32 IR; /* Instruction register */ - uint32 i_flags=0; /* Instruction description flags from table */ - uint32 t; /* Temporary */ - uint32 temp2; /* Temporary */ - uint32 bc=0; /* Temporary bit count */ - uint16 opr; /* Top half of Instruction register */ - uint16 OP; /* Six bit instruction opcode */ - uint16 chan; /* I/O channel address */ - uint16 lchan; /* Logical I/O channel address */ - uint16 suba; /* I/O subaddress */ - uint16 lchsa; /* logical I/O channel & subaddress */ - uint16 rchsa; /* real I/O channel & subaddress */ - uint8 FC; /* Current F&C bits */ - uint8 EXM_EXR=0; /* PC Increment for EXM/EXR instructions */ - uint32 reg; /* GPR or Base register bits 6-8 */ - uint32 sreg; /* Source reg in from bits 9-11 reg-reg instructions */ - uint32 ix = 0; /* index register */ - uint32 dbl; /* Double word */ - uint32 ovr=0; /* Overflow flag */ -//FORSTEP uint32 stopnext = 0; /* Stop on next instruction */ - uint32 int_icb; /* interrupt context block address */ - uint32 rstatus; /* temp return status */ - int32 int32a; /* temp int */ - int32 int32b; /* temp int */ - int32 int32c; /* temp int */ -#ifdef NOT_NOW - int32 ii; /* temp int */ + t_stat reason = 0; /* reason for stopping */ + t_uint64 dest = 0; /* Holds destination/source register */ + t_uint64 source = 0; /* Holds source or memory data */ + t_uint64 td; /* Temporary */ + t_int64 int64a; /* temp int */ + t_int64 int64b; /* temp int */ + t_int64 int64c; /* temp int */ + uint32 addr; /* Holds address of last access */ + uint32 temp; /* General holding place for stuff */ + uint32 IR; /* Instruction register */ + uint32 i_flags=0; /* Instruction description flags from table */ + uint32 t; /* Temporary */ + uint32 temp2; /* Temporary */ + uint32 bc=0; /* Temporary bit count */ + uint16 opr; /* Top half of Instruction register */ + uint16 OP; /* Six bit instruction opcode */ + uint16 chan; /* I/O channel address */ + uint16 lchan; /* Logical I/O channel address */ + uint16 suba; /* I/O subaddress */ + uint16 lchsa; /* logical I/O channel & subaddress */ + uint16 rchsa; /* real I/O channel & subaddress */ + uint8 FC; /* Current F&C bits */ + uint8 EXM_EXR=0; /* PC Increment for EXM/EXR instructions */ + uint32 reg; /* GPR or Base register bits 6-8 */ + uint32 sreg; /* Source reg in from bits 9-11 reg-reg instructions */ + uint32 ix = 0; /* index register */ + uint32 dbl; /* Double word */ + uint32 ovr=0; /* Overflow flag */ +//FORSTEP uint32 stopnext = 0; /* Stop on next instruction */ + uint32 int_icb; /* interrupt context block address */ + uint32 rstatus; /* temp return status */ + int32 int32a; /* temp int */ + int32 int32b; /* temp int */ + int32 int32c; /* temp int */ +//#define MPXTEST +#ifdef MPXTEST + int32 ii; /* temp int */ #endif wait_loop: - while (reason == 0) { /* loop until halted */ + while (reason == 0) { /* loop until halted */ // wait_loop: - if (sim_interval <= 0) { /* event queue? */ - reason = sim_process_event(); /* process */ + if (sim_interval <= 0) { /* event queue? */ + reason = sim_process_event(); /* process */ if (reason != SCPE_OK) { if (reason == SCPE_STEP) { - sim_debug(DEBUG_EXP, &cpu_dev, "Process Event step reason %08x interval %08x\n", - reason, sim_interval); -//FORSTEP stopnext = 1; + sim_debug(DEBUG_EXP, &cpu_dev, + "Process Event step reason %08x interval %08x\n", + reason, sim_interval); return reason; break; } else { - sim_debug(DEBUG_EXP, &cpu_dev, "Process Event other reason %08x interval %08x\n", - reason, sim_interval); + sim_debug(DEBUG_EXP, &cpu_dev, + "Process Event other reason %08x interval %08x\n", + reason, sim_interval); return reason; - break; /* process */ + break; /* process */ } } } @@ -1884,69 +1881,69 @@ wait_loop: if (sim_brk_summ) sim_debug(DEBUG_EXP, &cpu_dev, "Process Event sim_brk_summ = %08x\n", sim_brk_summ); - PC = PSD1 & 0xfffffe; /* get 24 bit addr from PSD1 */ + PC = PSD1 & 0xfffffe; /* get 24 bit addr from PSD1 */ /* stop simulator if user break requested */ if (sim_brk_summ && sim_brk_test(PC, SWMASK('E'))) { reason = STOP_IBKPT; sim_debug(DEBUG_EXP, &cpu_dev, "Process Event test reason %08x interval %08x\n", reason, sim_interval); - sim_interval= 0; /* count down */ + sim_interval= 0; /* count down */ break; } - sim_interval--; /* count down */ + sim_interval--; /* count down */ - if (drop_nop) { /* need to drop a nop? */ - drop_nop = 0; /* we dropped the nop */ + if (drop_nop) { /* need to drop a nop? */ + drop_nop = 0; /* we dropped the nop */ sim_debug(DEBUG_EXP, &cpu_dev, "CPU Drop NOP PSD1 %08x\n", PSD1); } - if (skipinstr) { /* need to skip interrupt test? */ - skipinstr = 0; /* skip only once */ - goto skipi; /* skip int test */ + if (skipinstr) { /* need to skip interrupt test? */ + skipinstr = 0; /* skip only once */ + goto skipi; /* skip int test */ } - if (waitqcnt > 0) { /* test for UTX delay */ - waitqcnt--; /* wait b4 ints */ -/*121420*/ if (waitqcnt == 0) -/*121420*/ irq_pend = 1; /* start scanning interrupts again */ + if (waitqcnt > 0) { /* test for UTX delay */ + waitqcnt--; /* wait b4 ints */ + if (waitqcnt == 0) + irq_pend = 1; /* start scanning interrupts again */ } /* we are booting the system, so see if boot channel prog is completed */ if (loading) { uint32 il; - uint32 chsa = scan_chan(&il); /* go scan for load complete pending */ - if (chsa != 0) { /* see if a boot channel/subaddress were returned */ + uint32 chsa = scan_chan(&il); /* go scan for load complete pending */ + if (chsa != 0) { /* see if a boot channel/subaddress were returned */ /* take interrupt, store the PSD, fetch new PSD */ - PSD1 = TPSD[0]; /* PSD1 from location 0 */ - PSD2 = TPSD[1]; /* PSD2 from location 4 */ - CC = PSD1 & 0x78000000; /* extract bits 1-4 from PSD1 */ - MODES = PSD1 & 0x87000000; /* extract bits 0, 5, 6, 7 from PSD 1 */ - CPUSTATUS &= ~0x87000000; /* reset bits in CPUSTATUS */ - CPUSTATUS |= MODES; /* now insert into CPUSTATUS */ + PSD1 = TPSD[0]; /* PSD1 from location 0 */ + PSD2 = TPSD[1]; /* PSD2 from location 4 */ + CC = PSD1 & 0x78000000; /* extract bits 1-4 from PSD1 */ + MODES = PSD1 & 0x87000000; /* extract bits 0, 5, 6, 7 from PSD 1 */ + CPUSTATUS &= ~0x87000000; /* reset bits in CPUSTATUS */ + CPUSTATUS |= MODES; /* now insert into CPUSTATUS */ sim_debug(DEBUG_IRQ, &cpu_dev, "Boot Loading PSD1 %.8x PSD2 %.8x\n", PSD1, PSD2); /* set interrupt blocking state in CPUSTATUS */ - CPUSTATUS |= BIT24; /* set blocked state in cpu status, bit 24 too */ - MODES |= BLKMODE; /* set blocked in mode to */ - PSD2 &= ~RETMBIT; /* turn off retain bit in PSD2 */ - PSD2 &= ~RETBBIT; /* turn off retain block mode bit in PSD2 */ + CPUSTATUS |= BIT24; /* set blocked state in cpu status, bit 24 too */ + MODES |= BLKMODE; /* set blocked in mode to */ + PSD2 &= ~RETMBIT; /* turn off retain bit in PSD2 */ + PSD2 &= ~RETBBIT; /* turn off retain block mode bit in PSD2 */ - SPAD[0xf5] = PSD2; /* save the current PSD2 */ - SPAD[0xf9] = CPUSTATUS; /* save the cpu status in SPAD */ - loading = 0; /* we are done loading */ + SPAD[0xf5] = PSD2; /* save the current PSD2 */ + SPAD[0xf9] = CPUSTATUS; /* save the cpu status in SPAD */ + loading = 0; /* we are done loading */ sim_debug(DEBUG_IRQ, &cpu_dev, "Load Skipinstr %1x set loading PSD1 %08x PSD2 %08x CPUSTATUS %08x\n", skipinstr, PSD1, PSD2, CPUSTATUS); - goto skipi; /* skip int test */ + goto skipi; /* skip int test */ } /* process any channel programs that are queued */ if (RDYQ_Num() && (skipinstr == 0)) { - uint32 chsa; /* channel/sub adddress */ - int32 stat; /* return status 0/1 from loadccw */ + uint32 chsa; /* channel/sub adddress */ + int32 stat; /* return status 0/1 from loadccw */ - if (waitrdyq > 0) { /* see if we are waiting to start */ + if (waitrdyq > 0) { /* see if we are waiting to start */ waitrdyq--; } else /* we have entries, continue channel program */ @@ -1954,33 +1951,33 @@ wait_loop: sim_debug(DEBUG_XIO, &cpu_dev, "CPU RDYQ entry loading for chsa %04x starting irq_pend %01x irq_auto %01x\n", chsa, irq_pend, irq_auto); - stat = cont_chan(chsa); /* resume the channel program */ - if (stat == SCPE_OK) /* done, status stored */ + stat = cont_chan(chsa); /* resume the channel program */ + if (stat == SCPE_OK) /* done, status stored */ sim_debug(DEBUG_XIO, &cpu_dev, "CPU RDYQ entry loading for chsa %04x processed\n", chsa); } } - goto wait_loop; /* continue waiting */ + goto wait_loop; /* continue waiting */ } /* we get here when not booting */ /* process any pending interrupts */ if ((irq_pend || wait4int) && (irq_auto == 0)) { /* see if ints are pending */ uint32 ilev; - uint32 oldstatus = CPUSTATUS; /* keep for retain blocking state */ - SPAD[0xf9] = CPUSTATUS; /* save the cpu status in SPAD */ + uint32 oldstatus = CPUSTATUS; /* keep for retain blocking state */ + SPAD[0xf9] = CPUSTATUS; /* save the cpu status in SPAD */ - int_icb = scan_chan(&ilev); /* no, go scan for I/O int pending */ - if (int_icb != 0) { /* was ICB returned for an I/O or interrupt */ - uint32 il = ilev; /* get the interrupt level */ + int_icb = scan_chan(&ilev); /* no, go scan for I/O int pending */ + if (int_icb != 0) { /* was ICB returned for an I/O or interrupt */ + uint32 il = ilev; /* get the interrupt level */ sim_debug(DEBUG_IRQ, &cpu_dev, "<|>Normal int return icb %06x level %02x irq_pend %1x wait4int %1x\n", int_icb, il, irq_pend, wait4int); /* take interrupt, store the PSD, fetch new PSD */ - bc = PSD2 & 0x3ff8; /* get copy of cpix */ - M[int_icb>>2] = PSD1&0xfffffffe;/* store PSD 1 */ - M[(int_icb>>2)+1] = PSD2; /* store PSD 2 */ + bc = PSD2 & 0x3ff8; /* get copy of cpix */ + M[int_icb>>2] = PSD1&0xfffffffe; /* store PSD 1 */ + M[(int_icb>>2)+1] = PSD2; /* store PSD 2 */ sim_debug(DEBUG_IRQ, &cpu_dev, "<|>Normal int cpix %04x OPSD1 %08x OPSD2 %08x\n", bc, PSD1, PSD2); @@ -1988,32 +1985,32 @@ wait_loop: sim_debug(DEBUG_IRQ, &cpu_dev, "<|> GPR[%d] %.8x GPR[%d] %.8x\n", ix, GPR[ix], ix+1, GPR[ix+1]); } - PSD1 = M[(int_icb>>2)+2]; /* get new PSD 1 */ + PSD1 = M[(int_icb>>2)+2]; /* get new PSD 1 */ PSD2 = (M[(int_icb>>2)+3] & ~0x3fff) | bc; /* get new PSD 2 w/old cpix */ /* I/O status DW address will be in WD 6 */ /* set new map mode and interrupt blocking state in CPUSTATUS */ - CC = PSD1 & 0x78000000; /* extract bits 1-4 from PSD1 */ - MODES = PSD1 & 0x87000000; /* extract bits 0, 5, 6, 7 from PSD 1 */ - CPUSTATUS &= ~0x87000080; /* reset bits in CPUSTATUS */ - CPUSTATUS |= MODES; /* now insert into CPUSTATUS */ + CC = PSD1 & 0x78000000; /* extract bits 1-4 from PSD1 */ + MODES = PSD1 & 0x87000000; /* extract bits 0, 5, 6, 7 from PSD 1 */ + CPUSTATUS &= ~0x87000080; /* reset bits in CPUSTATUS */ + CPUSTATUS |= MODES; /* now insert into CPUSTATUS */ if (PSD2 & MAPBIT) { - CPUSTATUS |= BIT8; /* set bit 8 of cpu status to mapped */ - MODES |= MAPMODE; /* set mapped mode */ + CPUSTATUS |= BIT8; /* set bit 8 of cpu status to mapped */ + MODES |= MAPMODE; /* set mapped mode */ } else { - CPUSTATUS &= ~BIT8; /* reset bit 8 of cpu status */ - MODES &= ~MAPMODE; /* reset set mapped mode */ + CPUSTATUS &= ~BIT8; /* reset bit 8 of cpu status */ + MODES &= ~MAPMODE; /* reset set mapped mode */ } - if ((PSD2 & RETBBIT) == 0) { /* is it retain blocking state, bit 48 set */ + if ((PSD2 & RETBBIT) == 0) { /* is it retain blocking state, bit 48 set */ /* retain blocking state is off, use bit 49 to set new blocking state */ - if (PSD2 & SETBBIT) { /* no, is it set blocking state bit 49 set*/ + if (PSD2 & SETBBIT) { /* no, is it set blocking state bit 49 set*/ /* new blocking state is blocked when bits 48=0 & bit 49=1 */ - CPUSTATUS |= BIT24; /* yes, set blk state in cpu status bit 24 */ - MODES |= BLKMODE; /* set blocked mode */ + CPUSTATUS |= BIT24; /* yes, set blk state in cpu status bit 24 */ + MODES |= BLKMODE; /* set blocked mode */ /* This test fixed the hangs on terminal input for diags & UTX! */ - t = SPAD[il+0x80]; /* get spad entry for interrupt */ + t = SPAD[il+0x80]; /* get spad entry for interrupt */ /* Class F I/O spec says to reset active interrupt if user's */ /* interrupt service routine runs with interrupts blocked */ if (((t & 0x0f800000) == 0x0f000000) || /* if class F clear interrupt */ @@ -2026,7 +2023,7 @@ wait_loop: "<|>Auto-reset irq_auto NOT zero %x INTS[%02x] %08x SPAD[%02x] %08x\n", irq_auto, il, INTS[il], il+0x80, SPAD[il+0x80]); } - irq_auto = il; /* show processing in blocked mode */ + irq_auto = il; /* show processing in blocked mode */ sim_debug(DEBUG_IRQ, &cpu_dev, "<|>Auto-reset interrupt INTS[%02x] %08x SPAD[%02x] %08x simi %02x\n", il, INTS[il], il+0x80, SPAD[il+0x80], sim_interval); @@ -2040,23 +2037,23 @@ wait_loop: sim_debug(DEBUG_IRQ, &cpu_dev, "<|>RUN ACTIVE interrupt INTS[%02x] %08x SPAD[%02x] %08x\n", il, INTS[il], il+0x80, SPAD[il+0x80]); - CPUSTATUS &= ~BIT24; /* no, reset blk state in cpu status bit 24 */ - MODES &= ~BLKMODE; /* reset blocked mode */ + CPUSTATUS &= ~BIT24; /* no, reset blk state in cpu status bit 24 */ + MODES &= ~BLKMODE; /* reset blocked mode */ } } else { /* handle retain blocking state */ - PSD2 &= ~RETMBIT; /* turn off retain bit in PSD2 */ + PSD2 &= ~RETMBIT; /* turn off retain bit in PSD2 */ /* set new blocking state in PSD2 */ - PSD2 &= ~(SETBBIT|RETBBIT); /* clear bit 48 & 49 to be unblocked */ - MODES &= ~(BLKMODE|RETMODE);/* reset blocked & retain mode bits */ - if (oldstatus & BIT24) { /* see if old mode is blocked */ - PSD2 |= SETBBIT; /* set to blocked state */ - MODES |= BLKMODE; /* set blocked mode */ + PSD2 &= ~(SETBBIT|RETBBIT); /* clear bit 48 & 49 to be unblocked */ + MODES &= ~(BLKMODE|RETMODE); /* reset blocked & retain mode bits */ + if (oldstatus & BIT24) { /* see if old mode is blocked */ + PSD2 |= SETBBIT; /* set to blocked state */ + MODES |= BLKMODE; /* set blocked mode */ } } - SPAD[0xf5] = PSD2; /* save the current PSD2 */ - SPAD[0xf9] = CPUSTATUS; /* save the cpu status in SPAD */ + SPAD[0xf5] = PSD2; /* save the current PSD2 */ + SPAD[0xf9] = CPUSTATUS; /* save the cpu status in SPAD */ sim_debug(DEBUG_IRQ, &cpu_dev, "<|>Int %02x OPSD1 %08x OPSD2 %08x NPSD1 %08x NPSD2 %08x\n", il, RMW(int_icb), RMW(int_icb+4), PSD1, PSD2); @@ -2068,32 +2065,30 @@ wait_loop: sim_debug(DEBUG_IRQ, &cpu_dev, "<|>Int2 %02x ICBA %06x IOCLA %06x STAT %08x SW1 %08x SW2 %08x\n", il, int_icb, RMW(int_icb+16), RMW(int_icb+20), RMW(bc), RMW(bc+4)); - wait4int = 0; /* wait is over for int */ -/*917*/ drop_nop = 0; /* no nop skipping */ - goto skipi; /* skip int test */ + wait4int = 0; /* wait is over for int */ + drop_nop = 0; /* no nop skipping */ + goto skipi; /* skip int test */ } } /* process IOCL entries that are waiting */ if (RDYQ_Num()) { - uint32 chsa; /* channel/sub adddress */ - CHANP *chp; /* get channel prog pointer */ - chsa = RDYQ[RDYQOUT]; /* get the next entry */ - chp = find_chanp_ptr(chsa); /* get channel prog pointer */ + uint32 chsa; /* channel/sub adddress */ + CHANP *chp; /* get channel prog pointer */ + chsa = RDYQ[RDYQOUT]; /* get the next entry */ + chp = find_chanp_ptr(chsa); /* get channel prog pointer */ if (chp->chan_byte == BUFF_NEXT) { /* we have entries, continue channel program */ -#ifndef USE_RDYQ if (waitrdyq > 0) { waitrdyq--; } else -#endif if (RDYQ_Get(&chsa) == SCPE_OK) { /* get chsa for program */ int32 stat; CHANP *chp = find_chanp_ptr(chsa); /* get channel prog pointer */ sim_debug(DEBUG_XIO, &cpu_dev, "scan_chan CPU RDYQ entry for chsa %04x starting byte %02x\n", chsa, chp->chan_byte); - stat = cont_chan(chsa); /* resume the channel program */ + stat = cont_chan(chsa); /* resume the channel program */ if (stat == SCPE_OK) sim_debug(DEBUG_XIO, &cpu_dev, "scan_chan CPU RDYQ entry for chsa %04x processed byte %04x\n", @@ -2107,25 +2102,25 @@ wait_loop: } /* see if in wait instruction */ - if (wait4int) { /* keep waiting */ + if (wait4int) { /* keep waiting */ /* tell simh we will be waiting */ - sim_idle(TMR_RTC, 1); /* wait for clock tick */ - irq_pend = 1; /* start scanning interrupts again */ - goto wait_loop; /* continue waiting */ + sim_idle(TMR_RTC, 1); /* wait for clock tick */ + irq_pend = 1; /* start scanning interrupts again */ + goto wait_loop; /* continue waiting */ } /* Check for external interrupt here */ /* see if we have an attention request from console */ if (!skipinstr && attention_trap) { - TRAPME = attention_trap; /* get trap number */ - attention_trap = 0; /* clear flag */ + TRAPME = attention_trap; /* get trap number */ + attention_trap = 0; /* clear flag */ sim_debug(DEBUG_XIO, &cpu_dev, "Attention TRAP %04x\n", TRAPME); - goto newpsd; /* got process trap */ + goto newpsd; /* got process trap */ } skipi: - i_flags = 0; /* do not update pc if MF or NPM */ - TRAPSTATUS = CPUSTATUS & 0x57; /* clear all trap status except cpu type */ + i_flags = 0; /* do not update pc if MF or NPM */ + TRAPSTATUS = CPUSTATUS & 0x57; /* clear all trap status except cpu type */ /* check for breakpoint request */ if (sim_brk_summ && sim_brk_test(PC, SWMASK('E'))) { @@ -2141,45 +2136,44 @@ skipi: if ((CPU_MODEL <= MODEL_27) || (CPU_MODEL == MODEL_67) || (CPU_MODEL == MODEL_87) || (CPU_MODEL == MODEL_97)) { if ((TRAPME == MAPFLT) || (TRAPME == NPMEM)) { - i_flags |= HLF; /* assume half word instr */ -/*DIAG*/ PSD1 &= ~BIT31; /* force off last right */ + i_flags |= HLF; /* assume half word instr */ + PSD1 &= ~BIT31; /* force off last right */ // fix for 32/67 test 32/3 in MMM diag if ((CPU_MODEL == MODEL_27) || (CPU_MODEL == MODEL_67)) - i_flags |= BT; /* do not update pc if MF or NPM */ + i_flags |= BT; /* do not update pc if MF or NPM */ else - i_flags &= ~BT; /* do not update pc if MF or NPM */ + i_flags &= ~BT; /* do not update pc if MF or NPM */ } } else { if ((TRAPME == PRIVVIOL_TRAP) && (CPU_MODEL == MODEL_V9)) { - i_flags |= HLF; /* assume half word instr */ + i_flags |= HLF; /* assume half word instr */ drop_nop = 0; - i_flags &= ~BT; /* no branch taken */ -/*DIAG*/ PSD1 &= ~BIT31; /* force off last right */ + i_flags &= ~BT; /* no branch taken */ + PSD1 &= ~BIT31; /* force off last right */ } } sim_debug(DEBUG_TRAP, &cpu_dev, "read_instr2 TRAPME %04x PSD %08x %08x i_flags %04x drop_nop %1x\n", TRAPME, PSD1, PSD2, i_flags, drop_nop); - goto newpsd; /* got process trap */ + goto newpsd; /* got process trap */ } - if (PSD1 & 2) { /* see if executing right half */ + if (PSD1 & 2) { /* see if executing right half */ /* we have a rt hw instruction */ - IR <<= 16; /* put instruction in left hw */ + IR <<= 16; /* put instruction in left hw */ if ((CPU_MODEL <= MODEL_27) || (CPU_MODEL == MODEL_87) || (CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9)) { - drop_nop = 0; /* not dropping nop for these machines */ - goto exec; /* machine does not drop nop instructions */ + drop_nop = 0; /* not dropping nop for these machines */ + goto exec; /* machine does not drop nop instructions */ } /* We have 67 or V6 and have a rt hw instruction */ - if (IR == 0x00020000) { /* is this a NOP from rt hw? */ + if (IR == 0x00020000) { /* is this a NOP from rt hw? */ PSD1 = (PSD1 + 2) | (((PSD1 & 2) >> 1) & 1); /* skip this instruction */ if (skipinstr) sim_debug(DEBUG_IRQ, &cpu_dev, "2Rt HW instruction skipinstr %1x is set PSD1 %08x PSD2 %08x CPUSTATUS %08x\n", skipinstr, PSD1, PSD2, CPUSTATUS); - goto skipi; /* go read next instruction */ -/////0122 goto wait_loop; /* continue waiting */ + goto skipi; /* go read next instruction */ } if (skipinstr) sim_debug(DEBUG_IRQ, &cpu_dev, @@ -2188,18 +2182,18 @@ skipi: } else { /* we have a left hw or fullword instruction */ /* see if we can drop a rt hw nop instruction */ - OP = (IR >> 24) & 0xFC; /* this is a 32/67 or above, get OP */ + OP = (IR >> 24) & 0xFC; /* this is a 32/67 or above, get OP */ if ((CPU_MODEL <= MODEL_27) || (CPU_MODEL == MODEL_87) || (CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9)) - goto exec; /* old machines did not drop nop instructions */ + goto exec; /* old machines did not drop nop instructions */ if (PSD1 & BASEBIT) - i_flags = base_mode[OP>>2]; /* set the BM instruction processing flags */ + i_flags = base_mode[OP>>2]; /* set the BM instruction processing flags */ else - i_flags = nobase_mode[OP>>2]; /* set the NBM instruction processing flags */ - if ((i_flags & 0xf) == HLF) { /* this is left HW instruction */ - if ((IR & 0xffff) == 0x0002) { /* see if rt hw is a nop */ + i_flags = nobase_mode[OP>>2]; /* set the NBM instruction processing flags */ + if ((i_flags & 0xf) == HLF) { /* this is left HW instruction */ + if ((IR & 0xffff) == 0x0002) { /* see if rt hw is a nop */ /* treat this as a fw instruction */ - drop_nop = 1; /* we need to skip nop next time */ + drop_nop = 1; /* we need to skip nop next time */ sim_debug(DEBUG_DETAIL, &cpu_dev, "CPU setting Drop NOP PSD1 %08x IR %08x\n", PSD1, IR); } @@ -2208,148 +2202,151 @@ skipi: exec: /* temp saves for debugging */ - OIR = IR; /* save the instruction */ - OPSD1 = PSD1; /* save the old PSD1 */ - OPSD2 = PSD2; /* save the old PSD2 */ - TRAPSTATUS = CPUSTATUS & 0x57; /* clear all trap status except cpu type */ + OIR = IR; /* save the instruction */ + OPSD1 = PSD1; /* save the old PSD1 */ + OPSD2 = PSD2; /* save the old PSD2 */ + TRAPSTATUS = CPUSTATUS & 0x57; /* clear all trap status except cpu type */ /* Split instruction into pieces */ - PC = PSD1 & 0xfffffe; /* get 24 bit addr from PSD1 */ - sim_debug(DEBUG_DETAIL, &cpu_dev, "-----Instr @ PC %08x PSD1 %08x PSD2 %08x IR %08x drop_nop %x\n", + PC = PSD1 & 0xfffffe; /* get 24 bit addr from PSD1 */ + sim_debug(DEBUG_DETAIL, &cpu_dev, + "-----Instr @ PC %08x PSD1 %08x PSD2 %08x IR %08x drop_nop %x\n", PC, PSD1, PSD2, IR, drop_nop); /* Update history for this instruction */ if (hst_lnt) { - hst_p += 1; /* next history location */ - if (hst_p >= hst_lnt) /* check for wrap */ - hst_p = 0; /* start over at beginning */ - hst[hst_p].opsd1 = OPSD1; /* set original psd1 */ - hst[hst_p].opsd2 = OPSD2; /* set original psd2 */ - hst[hst_p].oir = OIR; /* set original instruction */ + hst_p += 1; /* next history location */ + if (hst_p >= hst_lnt) /* check for wrap */ + hst_p = 0; /* start over at beginning */ + hst[hst_p].opsd1 = OPSD1; /* set original psd1 */ + hst[hst_p].opsd2 = OPSD2; /* set original psd2 */ + hst[hst_p].oir = OIR; /* set original instruction */ } - opr = (IR >> 16) & MASK16; /* use upper half of instruction */ - OP = (opr >> 8) & 0xFC; /* Get opcode (bits 0-5) left justified */ + opr = (IR >> 16) & MASK16; /* use upper half of instruction */ + OP = (opr >> 8) & 0xFC; /* Get opcode (bits 0-5) left justified */ FC = ((IR & F_BIT) ? 0x4 : 0) | (IR & 3); /* get F & C bits for addressing */ - reg = (opr >> 7) & 0x7; /* dest reg or xr on base mode */ - sreg = (opr >> 4) & 0x7; /* src reg for reg-reg instructions or BR instr */ - dbl = 0; /* no doubleword instruction */ - ovr = 0; /* no overflow or arithmetic exception either */ - dest = (t_uint64)IR; /* assume memory address specified */ - CC = PSD1 & 0x78000000; /* save CC's if any */ - MODES = PSD1 & 0x87000000; /* insert bits 0, 5, 6, 7 from PSD 1 */ - CPUSTATUS &= ~0x87000000; /* reset those bits in CPUSTATUS */ - CPUSTATUS |= MODES; /* now insert them into CPUSTATUS */ + reg = (opr >> 7) & 0x7; /* dest reg or xr on base mode */ + sreg = (opr >> 4) & 0x7; /* src reg for reg-reg instructions or BR instr */ + dbl = 0; /* no doubleword instruction */ + ovr = 0; /* no overflow or arithmetic exception either */ + dest = (t_uint64)IR; /* assume memory address specified */ + CC = PSD1 & 0x78000000; /* save CC's if any */ + MODES = PSD1 & 0x87000000; /* insert bits 0, 5, 6, 7 from PSD 1 */ + CPUSTATUS &= ~0x87000000; /* reset those bits in CPUSTATUS */ + CPUSTATUS |= MODES; /* now insert them into CPUSTATUS */ if (PSD2 & MAPBIT) - MODES |= MAPMODE; /* set mapped mode */ + MODES |= MAPMODE; /* set mapped mode */ if (MODES & BASEBIT) { - i_flags = base_mode[OP>>2]; /* set the instruction processing flags */ - addr = IR & RMASK; /* get address offset from instruction */ + i_flags = base_mode[OP>>2]; /* set the instruction processing flags */ + addr = IR & RMASK; /* get address offset from instruction */ sim_debug(DEBUG_DETAIL, &cpu_dev, "Base OP %04x i_flags %04x addr %08x\n", OP, i_flags, addr); switch(i_flags & 0xf) { case HLF: - source = GPR[sreg]; /* get the src reg from instruction */ + source = GPR[sreg]; /* get the src reg from instruction */ break; case IMM: - if (PC & 02) { /* if pc is on HW boundry, bad address */ - TRAPME = ADDRSPEC_TRAP; /* bad address, error */ + if (PC & 02) { /* if pc is on HW boundry, bad address */ + TRAPME = ADDRSPEC_TRAP; /* bad address, error */ sim_debug(DEBUG_TRAP, &cpu_dev, "ADDRSPEC1 OP %04x addr %08x\n", OP, addr); - goto newpsd; /* go execute the trap now */ + goto newpsd; /* go execute the trap now */ } break; case ADR: - ix = (IR >> 20) & 7; /* get index reg from instruction */ + ix = (IR >> 20) & 7; /* get index reg from instruction */ if (ix != 0) - addr += (GPR[ix] & MASK24); /* if not zero, add in reg contents */ + addr += (GPR[ix] & MASK24); /* if not zero, add in reg contents */ case WRD: - if (PC & 02) { /* if pc is on HW boundry, bad address */ - TRAPME = ADDRSPEC_TRAP; /* bad address, error */ + if (PC & 02) { /* if pc is on HW boundry, bad address */ + TRAPME = ADDRSPEC_TRAP; /* bad address, error */ sim_debug(DEBUG_TRAP, &cpu_dev, "ADDRSPEC2 OP %04x addr %08x\n", OP, addr); - goto newpsd; /* go execute the trap now */ + goto newpsd; /* go execute the trap now */ } - ix = (IR >> 16) & 7; /* get base reg from instruction */ + ix = (IR >> 16) & 7; /* get base reg from instruction */ if (ix != 0) - addr += (BR[ix] & MASK24); /* if not zero, add to base reg contents */ - FC = ((IR & F_BIT) ? 4 : 0); /* get F bit from original instruction */ - FC |= addr & 3; /* set new C bits to address from orig or regs */ - addr &= MASK24; /* make pure 24 bit addr */ + addr += (BR[ix] & MASK24); /* if not zero, add to base reg contents */ + FC = ((IR & F_BIT) ? 4 : 0); /* get F bit from original instruction */ + FC |= addr & 3; /* set new C bits to address from orig or regs */ + addr &= MASK24; /* make pure 24 bit addr */ break; case INV: - TRAPME = UNDEFINSTR_TRAP; /* Undefined Instruction Trap */ + TRAPME = UNDEFINSTR_TRAP; /* Undefined Instruction Trap */ if ((CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9)) - TRAPSTATUS |= BIT0; /* set bit 0 of trap status */ - goto newpsd; /* handle trap */ + TRAPSTATUS |= BIT0; /* set bit 0 of trap status */ + goto newpsd; /* handle trap */ break; } } else { - i_flags = nobase_mode[OP>>2]; /* set the instruction processing flags */ - addr = IR & 0x7ffff; /* get 19 bit address from instruction */ + i_flags = nobase_mode[OP>>2]; /* set the instruction processing flags */ + addr = IR & 0x7ffff; /* get 19 bit address from instruction */ if (PC >= 0x80000) { - TRAPME = MAPFAULT_TRAP; /* Map Fault Trap */ + TRAPME = MAPFAULT_TRAP; /* Map Fault Trap */ // DIAG add 97 for correct PSD address CN.MMM test 32, subtest 1 fails if ((CPU_MODEL <= MODEL_27) || (CPU_MODEL == MODEL_67) || (CPU_MODEL == MODEL_87) || (CPU_MODEL == MODEL_97)) { // DIAG fix for 32/87 test 33/2, clear psd bit 31 if ((CPU_MODEL == MODEL_87)) -/*DIAG*/ PSD1 &= ~BIT31; /* force off last right */ + PSD1 &= ~BIT31; /* force off last right */ // DIAG fix 32/27 32/67 for diag MMM test 33/2 if ((CPU_MODEL <= MODEL_27) || (CPU_MODEL == MODEL_67)) - i_flags |= BT; /* do not update pc if MAPFAULT on 27 */ + i_flags |= BT; /* do not update pc if MAPFAULT on 27 */ else - i_flags &= ~BT; /* do not update pc if MF or NPM */ - i_flags |= HLF; /* assume half word instr */ + i_flags &= ~BT; /* do not update pc if MF or NPM */ + i_flags |= HLF; /* assume half word instr */ } if ((CPU_MODEL <= MODEL_27)) { /* 77, 27 rolls to zero, not 80000 */ - PSD1 &= 0xff07ffff; /* remove overflow bits */ + PSD1 &= 0xff07ffff; /* remove overflow bits */ } else { - PSD1 &= 0xff0fffff; /* leave overflow bit for trap addr */ + PSD1 &= 0xff0fffff; /* leave overflow bit for trap addr */ } sim_debug(DEBUG_TRAP, &cpu_dev, - "PC over 80000 PC %08x Base OP %02x i_flags %04x addr %06x PSD %08x %08x\n", + "PC over 80000 PC %08x Base OP %02x i_flags %04x addr %06x PSD %08x %08x\n", PC, OP, i_flags, addr, PSD1, PSD2); if ((CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9)) - TRAPSTATUS |= BIT0; /* set bit 0 of trap status */ + TRAPSTATUS |= BIT0; /* set bit 0 of trap status */ else - TRAPSTATUS |= BIT19; /* set bit 19 of trap status */ - goto newpsd; /* handle trap */ + TRAPSTATUS |= BIT19; /* set bit 19 of trap status */ + goto newpsd; /* handle trap */ } - sim_debug(DEBUG_DETAIL, &cpu_dev, "Non Based i_flags %04x addr %08x\n", i_flags, addr); + sim_debug(DEBUG_DETAIL, &cpu_dev, + "Non Based i_flags %04x addr %08x\n", i_flags, addr); /* non base mode instructions have bit 0 of the instruction set */ /* for word length instructions and zero for halfword instructions */ /* the LA (op=0x34) is the only exception. So test for PC on a halfword */ /* address and trap if word opcode is in right hw */ - if (PC & 02) { /* if pc is on HW boundry, addr trap if bit zero set */ + /* if pc is on HW boundry, addr trap if bit zero set */ + if (PC & 02) { if ((OP == 0x34) || (OP & 0x80)) { - i_flags |= HLF; /* diags treats these as hw instructions */ - TRAPME = UNDEFINSTR_TRAP; /* Undefined Instruction Trap */ - goto newpsd; /* go execute the trap now */ + i_flags |= HLF; /* diags treats these as hw instructions */ + TRAPME = UNDEFINSTR_TRAP; /* Undefined Instruction Trap */ + goto newpsd; /* go execute the trap now */ } } switch(i_flags & 0xf) { - case HLF: /* halfword instruction */ - source = GPR[sreg]; /* get the src reg contents */ + case HLF: /* halfword instruction */ + source = GPR[sreg]; /* get the src reg contents */ break; - case IMM: /* Immediate mode */ - if (PC & 02) { /* if pc is on HW boundry, bad address */ - TRAPME = ADDRSPEC_TRAP; /* bad address, error */ + case IMM: /* Immediate mode */ + if (PC & 02) { /* if pc is on HW boundry, bad address */ + TRAPME = ADDRSPEC_TRAP; /* bad address, error */ sim_debug(DEBUG_TRAP, &cpu_dev, "ADDRSPEC3 OP %04x addr %08x\n", OP, addr); - goto newpsd; /* go execute the trap now */ + goto newpsd; /* go execute the trap now */ } break; - case ADR: /* Normal addressing mode */ - ix = (IR >> 21) & 3; /* get the index reg if specified */ + case ADR: /* Normal addressing mode */ + ix = (IR >> 21) & 3; /* get the index reg if specified */ if (ix != 0) { - addr += GPR[ix]; /* if not zero, add in reg contents */ + addr += GPR[ix]; /* if not zero, add in reg contents */ FC = ((IR & F_BIT) ? 4 : 0); /* get F bit from original instruction */ - FC |= addr & 3; /* set new C bits to address from orig or regs */ + FC |= addr & 3; /* set new C bits to address from orig or regs */ } /* wart alert! */ @@ -2362,44 +2359,45 @@ exec: /* if IX == Ix => dest = ind + reg */ /* fall through */ - case WRD: /* Word addressing, no index */ - bc = 0xC0000000; /* set bits 0, 1 for instruction if not indirect */ - t = IR; /* get current IR */ - addr &= MASK24; /* make pure 24 bit addr */ - while ((t & IND) != 0) { /* process indirection */ + case WRD: /* Word addressing, no index */ + bc = 0xC0000000; /* set bits 0, 1 for instruction if not indirect */ + t = IR; /* get current IR */ + addr &= MASK24; /* make pure 24 bit addr */ + while ((t & IND) != 0) { /* process indirection */ if ((TRAPME = Mem_read(addr, &temp))) { /* get the word from memory */ sim_debug(DEBUG_TRAP, &cpu_dev, "case WRD Mem_read status %02x @ %08x OP %04x\n", TRAPME, addr, OP); if (CPU_MODEL == MODEL_V9) /* V9 wants bit0 set in pfault */ if (TRAPME == DMDPG) /* demand page request */ pfault |= 0x80000000; /* set instruction fetch paging error */ - goto newpsd; /* memory read error or map fault */ + goto newpsd; /* memory read error or map fault */ } - bc = temp & 0xC0000000; /* save new bits 0, 1 from indirect location */ - CC = (temp & 0x78000000); /* save CC's from the last indirect word */ + bc = temp & 0xC0000000; /* save new bits 0, 1 from indirect location */ + CC = (temp & 0x78000000); /* save CC's from the last indirect word */ /* process new X, I, ADDR fields */ - addr = temp & MASK19; /* get just the addr */ - ix = (temp >> 21) & 3; /* get the index reg from indirect word */ + addr = temp & MASK19; /* get just the addr */ + ix = (temp >> 21) & 3; /* get the index reg from indirect word */ if (ix != 0) addr += (GPR[ix] & MASK19); /* add the register to the address */ /* if no F or C bits set, use original, else new */ if ((temp & F_BIT) || (addr & 3)) FC = ((temp & F_BIT) ? 0x4 : 0) | (addr & 3); else { - addr |= (IR & F_BIT); /* copy F bit from instruction */ - addr |= (FC & 3); /* copy in last C bits */ + addr |= (IR & F_BIT); /* copy F bit from instruction */ + addr |= (FC & 3); /* copy in last C bits */ } - t = temp; /* go process next indirect location */ - temp &= MASK19; /* go process next indirect location */ - addr &= ~F_BIT; /* turn off F bit */ + t = temp; /* go process next indirect location */ + temp &= MASK19; /* go process next indirect location */ + addr &= ~F_BIT; /* turn off F bit */ } - dest = (t_uint64)addr; /* make into 64 bit variable */ + dest = (t_uint64)addr; /* make into 64 bit variable */ break; - case INV: /* Invalid instruction */ - TRAPME = UNDEFINSTR_TRAP; /* Undefined Instruction Trap */ + + case INV: /* Invalid instruction */ + TRAPME = UNDEFINSTR_TRAP; /* Undefined Instruction Trap */ if ((CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9)) - TRAPSTATUS |= BIT0; /* set bit 0 of trap status */ - goto newpsd; /* handle trap */ + TRAPSTATUS |= BIT0; /* set bit 0 of trap status */ + goto newpsd; /* handle trap */ break; } } @@ -2411,45 +2409,45 @@ exec: "case RM Mem_read status %02x @ %08x\n", TRAPME, addr); // DIAG add 97 for correct PSD address CN.MMM test 32, subtest 1 fails if ((TRAPME == MAPFLT) || (TRAPME == NPMEM) || (TRAPME == MPVIOL)) -/*DIAG*/ PSD1 &= ~BIT31; /* force off last right */ - goto newpsd; /* memory read error or map fault */ + PSD1 &= ~BIT31; /* force off last right */ + goto newpsd; /* memory read error or map fault */ } - source = (t_uint64)temp; /* make into 64 bit value */ + source = (t_uint64)temp; /* make into 64 bit value */ switch(FC) { - case 0: /* word address, extend sign */ + case 0: /* word address, extend sign */ source |= (source & MSIGN) ? D32LMASK : 0; break; - case 1: /* left hw */ - source >>= 16; /* move left hw to right hw*/ + case 1: /* left hw */ + source >>= 16; /* move left hw to right hw*/ /* Fall through */ - case 3: /* right hw or right shifted left hw */ - source &= RMASK; /* use just the right hw */ - if (source & 0x8000) { /* check sign of 16 bit value */ + case 3: /* right hw or right shifted left hw */ + source &= RMASK; /* use just the right hw */ + if (source & 0x8000) { /* check sign of 16 bit value */ /* sign extend the value to leftmost 48 bits */ source = LMASK | (source & RMASK); /* extend low 32 bits */ - source |= (D32LMASK); /* extend hi bits */ + source |= (D32LMASK); /* extend hi bits */ } break; - case 2: /* double word address */ - if ((addr & 7) != 2) { /* must be double word adddress */ - TRAPME = ADDRSPEC_TRAP; /* bad address, error */ + case 2: /* double word address */ + if ((addr & 7) != 2) { /* must be double word adddress */ + TRAPME = ADDRSPEC_TRAP; /* bad address, error */ sim_debug(DEBUG_TRAP, &cpu_dev, "ADDRSPEC4 case RM wd 1/3 Mem_read DW status %02x @ %08x src %08x\n", TRAPME, addr, (uint32)source); - goto newpsd; /* go execute the trap now */ + goto newpsd; /* go execute the trap now */ } if ((TRAPME = Mem_read(addr+4, &temp))) { /* get the 2nd word from memory */ sim_debug(DEBUG_TRAP, &cpu_dev, "case RM wd 2 Mem_read status %02x @ %08x\n", TRAPME, addr+4); - goto newpsd; /* memory read error or map fault */ + goto newpsd; /* memory read error or map fault */ } source = (source << 32) | (t_uint64)temp; /* merge in the low order 32 bits */ - dbl = 1; /* double word instruction */ + dbl = 1; /* double word instruction */ break; - case 4: /* byte mode, byte 0 */ - case 5: /* byte mode, byte 1 */ - case 6: /* byte mode, byte 2 */ - case 7: /* byte mode, byte 3 */ + case 4: /* byte mode, byte 0 */ + case 5: /* byte mode, byte 1 */ + case 6: /* byte mode, byte 2 */ + case 7: /* byte mode, byte 3 */ source = (source >> (8*(7-FC))) & 0xff; /* right justify addressed byte */ break; } @@ -2460,38 +2458,38 @@ exec: if ((TRAPME = Mem_read(addr, &temp))) { /* get the word from memory */ sim_debug(DEBUG_TRAP, &cpu_dev, "case RNX 2 Mem_read status %02x @ %08x\n", TRAPME, addr); - goto newpsd; /* memory read error or map fault */ + goto newpsd; /* memory read error or map fault */ } - source = (t_uint64)temp; /* make into 64 bit value */ + source = (t_uint64)temp; /* make into 64 bit value */ switch(FC) { - case 0: /* word address and no sign extend */ - source &= D32RMASK; /* just l/o 32 bits */ + case 0: /* word address and no sign extend */ + source &= D32RMASK; /* just l/o 32 bits */ break; - case 1: /* left hw */ - source >>= 16; /* move left hw to right hw*/ + case 1: /* left hw */ + source >>= 16; /* move left hw to right hw*/ /* Fall through */ - case 3: /* right hw or right shifted left hw */ - source &= RMASK; /* use just the right hw */ + case 3: /* right hw or right shifted left hw */ + source &= RMASK; /* use just the right hw */ break; - case 2: /* double word address */ - if ((addr & 7) != 2) { /* must be double word adddress */ - TRAPME = ADDRSPEC_TRAP; /* bad address, error */ + case 2: /* double word address */ + if ((addr & 7) != 2) { /* must be double word adddress */ + TRAPME = ADDRSPEC_TRAP; /* bad address, error */ sim_debug(DEBUG_TRAP, &cpu_dev, "ADDRSPEC5 OP %04x addr %08x\n", OP, addr); - goto newpsd; /* go execute the trap now */ + goto newpsd; /* go execute the trap now */ } if ((TRAPME = Mem_read(addr+4, &temp))) { /* get the 2nd word from memory */ sim_debug(DEBUG_TRAP, &cpu_dev, "case RNX wd 2 Mem_read status %02x @ %08x\n", TRAPME, addr+4); - goto newpsd; /* memory read error or map fault */ + goto newpsd; /* memory read error or map fault */ } source = (source << 32) | (t_uint64)temp; /* merge in the low order 32 bits */ - dbl = 1; /* double word instruction */ + dbl = 1; /* double word instruction */ break; - case 4: /* byte mode, byte 0 */ - case 5: /* byte mode, byte 1 */ - case 6: /* byte mode, byte 2 */ - case 7: /* byte mode, byte 3 */ + case 4: /* byte mode, byte 0 */ + case 5: /* byte mode, byte 1 */ + case 6: /* byte mode, byte 2 */ + case 7: /* byte mode, byte 3 */ source = (source >> (8*(7-FC))) & 0xff; /* right justify addressed byte */ break; } @@ -2544,6 +2542,10 @@ exec: sim_debug(DEBUG_DETAIL, &cpu_dev, "PSD %08x %08x SW OP %04x IR %08x addr %08x\n", PSD1, PSD2, OP, IR, addr); + + /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ + /* start processing the opcodes */ + /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ switch (OP>>2) { /* * For op-codes=00,04,08,0c,10,14,28,2c,38,3c,40,44,60,64,68 @@ -2553,303 +2555,303 @@ exec: /* |0 1 2 3 4 5|6 7 8 |9 10 11|12 13 14 15| */ /* | Op Code | DReg | SReg | Aug Code | */ /* |--------------------------------------| */ - case 0x00>>2: /* HLF - HLF */ /* CPU General operations */ - switch(opr & 0xF) { /* switch on aug code */ - case 0x0: /* HALT */ -#ifndef TRYMPX - if ((MODES & PRIVBIT) == 0) { /* must be privileged to halt */ -//sim_debug(DEBUG_EXP, &cpu_dev, "Privledged violation HALT\n"); - TRAPME = PRIVVIOL_TRAP; /* set the trap to take */ - if ((CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9)) - TRAPSTATUS |= BIT0; /* set bit 0 of trap status */ - else - TRAPSTATUS |= BIT19; /* set bit 19 of trap status */ - goto newpsd; /* Privlege violation trap */ - } - if (CPUSTATUS & BIT23) { /* Priv mode halt must be enabled */ - TRAPME = PRIVHALT_TRAP; /* set the trap to take */ - goto newpsd; /* Privlege mode halt trap */ - } + case 0x00>>2: /* HLF - HLF */ /* CPU General operations */ + switch(opr & 0xF) { /* switch on aug code */ + case 0x0: /* HALT */ +#ifndef TEMP4DEBUG + if ((MODES & PRIVBIT) == 0) { /* must be privileged to halt */ + TRAPME = PRIVVIOL_TRAP; /* set the trap to take */ + if ((CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9)) + TRAPSTATUS |= BIT0; /* set bit 0 of trap status */ + else + TRAPSTATUS |= BIT19; /* set bit 19 of trap status */ + goto newpsd; /* Privlege violation trap */ + } + if (CPUSTATUS & BIT23) { /* Priv mode halt must be enabled */ + TRAPME = PRIVHALT_TRAP; /* set the trap to take */ + goto newpsd; /* Privlege mode halt trap */ + } #endif - sim_debug(DEBUG_EXP, &cpu_dev, "Starting HALT instruction\n"); - - sim_debug(DEBUG_EXP, &cpu_dev, "\n[][][][][][][][][][] HALT [][][][][][][][][][]\n"); - sim_debug(DEBUG_EXP, &cpu_dev, "PSD1 %.8x PSD2 %.8x TRAPME %.4x CPUSTATUS %08x\n", + sim_debug(DEBUG_EXP, &cpu_dev, + "\n[][][][][][][][][][] HALT [][][][][][][][][][]\n"); + sim_debug(DEBUG_EXP, &cpu_dev, + "PSD1 %.8x PSD2 %.8x TRAPME %.4x CPUSTATUS %08x\n", PSD1, PSD2, TRAPME, CPUSTATUS); for (ix=0; ix<8; ix+=2) { - sim_debug(DEBUG_EXP, &cpu_dev, "GPR[%d] %.8x GPR[%d] %.8x\n", ix, GPR[ix], ix+1, GPR[ix+1]); + sim_debug(DEBUG_EXP, &cpu_dev, + "GPR[%d] %.8x GPR[%d] %.8x\n", ix, GPR[ix], ix+1, GPR[ix+1]); } - sim_debug(DEBUG_EXP, &cpu_dev, "[][][][][][][][][][] HALT [][][][][][][][][][]\n"); + sim_debug(DEBUG_EXP, &cpu_dev, + "[][][][][][][][][][] HALT [][][][][][][][][][]\n"); fprintf(stdout, "\r\n[][][][][][][][][][] HALT [][][][][][][][][][]\r\n"); - fprintf(stdout, "PSD1 %.8x PSD2 %.8x TRAPME %.4x\r\n", PSD1, PSD2, TRAPME); + fprintf(stdout, "PSD1 %.8x PSD2 %.8x TRAPME %.4x\r\n", + PSD1, PSD2, TRAPME); for (ix=0; ix<8; ix+=2) { - fprintf(stdout, "GPR[%d] %.8x GPR[%d] %.8x\r\n", ix, GPR[ix], ix+1, GPR[ix+1]); + fprintf(stdout, "GPR[%d] %.8x GPR[%d] %.8x\r\n", + ix, GPR[ix], ix+1, GPR[ix+1]); } if (MODES & BASEBIT) { /* see if based */ for (ix=0; ix<8; ix+=2) { - fprintf(stdout, "BR[%d] %.8x BR[%d] %.8x\r\n", ix, BR[ix], ix+1, BR[ix+1]); - } + fprintf(stdout, "BR[%d] %.8x BR[%d] %.8x\r\n", + ix, BR[ix], ix+1, BR[ix+1]); } - fprintf(stdout, "[][][][][][][][][][] HALT [][][][][][][][][][]\r\n"); -/*TEST DIAG*/ reason = STOP_HALT; /* do halt for now */ - break; - case 0x1: /* WAIT */ - if ((MODES & PRIVBIT) == 0) { /* must be privileged to wait */ -//sim_debug(DEBUG_EXP, &cpu_dev, "Privledged violation WAIT\n"); - TRAPME = PRIVVIOL_TRAP; /* set the trap to take */ - if ((CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9)) - TRAPSTATUS |= BIT0; /* set bit 0 of trap status */ - else - TRAPSTATUS |= BIT19; /* set bit 19 of trap status */ - goto newpsd; /* Privlege violation trap */ - } - /* if interrupts are blocked, system check trap */ - if (CPUSTATUS & BIT24) { /* status word bit 24 says blocked */ - TRAPME = SYSTEMCHK_TRAP; /* trap condition if F class */ - if ((CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9)) - TRAPSTATUS |= BIT12; /* set bit 0 of trap status */ - else - TRAPSTATUS |= BIT20; /* set bit 20 of trap status */ - goto newpsd; /* system check trap */ - } - if (wait4int == 0) { - time_t result = time(NULL); -// sim_debug(DEBUG_DETAIL, &cpu_dev, - sim_debug(DEBUG_IRQ, &cpu_dev, - "Starting WAIT mode %08x\n", (uint32)result); - } - wait4int = 1; /* show we are waiting for interrupt */ - /* tell simh we will be waiting */ - sim_idle(TMR_RTC, 0); /* wait for next pending device event */ - irq_pend = 1; /* start scanning interrupts again */ - i_flags |= BT; /* keep PC from being incremented while waiting */ - break; - case 0x2: /* NOP */ - break; - case 0x3: /* LCS */ - /* get console switches from memory loc 0x780 */ - if ((TRAPME = Mem_read(0x780, &GPR[reg]))) /* get the word from memory */ - goto newpsd; /* memory read error or map fault */ - set_CCs(GPR[reg], 0); /* set the CC's, CC1 = 0 */ - break; - case 0x4: /* ES */ - if (reg & 1) { /* see if odd reg specified */ - TRAPME = ADDRSPEC_TRAP; /* bad reg address, error */ - goto newpsd; /* go execute the trap now */ - } - /* reg is reg to extend sign into from reg+1 */ - GPR[reg] = (GPR[reg+1] & FSIGN) ? FMASK : 0; - set_CCs(GPR[reg], 0); /* set CCs, CC2 & CC3 */ - break; - case 0x5: /* RND */ - if (reg & 1) { /* see if odd reg specified */ - TRAPME = ADDRSPEC_TRAP; /* bad reg address, error */ - goto newpsd; /* go execute the trap now */ - } - temp = GPR[reg]; /* save the current contents of specified reg */ - t = (temp & FSIGN) != 0; /* set flag for sign bit not set in temp value */ - bc = 1; - t |= ((bc & FSIGN) != 0) ? 2 : 0; /* ditto for the bit value */ - if (GPR[reg+1] & FSIGN) { /* if sign of R+1 is set, incr R by 1 */ - temp += bc; /* add the bit value to the reg */ - /* if both signs are neg and result sign is positive, overflow */ - /* if both signs are pos and result sign is negative, overflow */ - if ((t == 3 && (temp & FSIGN) == 0) || - (t == 0 && (temp & FSIGN) != 0)) { - ovr = 1; /* we have an overflow */ - } - GPR[reg] = temp; /* update the R value */ - } else - ovr = 0; - set_CCs(temp, ovr); /* set the CC's, CC1 = ovr */ - /* the arithmetic exception will be handled */ - /* after instruction is completed */ - /* check for arithmetic exception trap enabled */ - if (ovr && (MODES & AEXPBIT)) { - TRAPME = AEXPCEPT_TRAP; /* set the trap type */ - goto newpsd; /* handle trap */ - } - break; - case 0x6: /* BEI */ - if ((MODES & PRIVBIT) == 0) { /* must be privileged to BEI */ -//sim_debug(DEBUG_EXP, &cpu_dev, "Privledged violation BEI\n"); - TRAPME = PRIVVIOL_TRAP; /* set the trap to take */ - if ((CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9)) - TRAPSTATUS |= BIT0; /* set bit 0 of trap status */ - else - TRAPSTATUS |= BIT19; /* set bit 19 of trap status */ - goto newpsd; /* Privlege violation trap */ - } - CPUSTATUS |= BIT24; /* into status word bit 24 too */ - PSD2 &= ~(SETBBIT|RETBBIT); /* clear bit 48 & 49 */ - MODES &= ~(BLKMODE|RETMODE);/* reset blocked & retain mode bits */ - PSD2 |= SETBBIT; /* set to blocked state */ - MODES |= BLKMODE; /* set blocked mode */ + } + fprintf(stdout, "[][][][][][][][][][] HALT [][][][][][][][][][]\r\n"); +/*TEST DIAG*/reason = STOP_HALT; /* do halt for now */ + break; - SPAD[0xf5] = PSD2; /* save the current PSD2 */ - SPAD[0xf9] = CPUSTATUS; /* save the cpu status in SPAD */ - break; - case 0x7: /* UEI */ - if ((MODES & PRIVBIT) == 0) { /* must be privileged to UEI */ -//sim_debug(DEBUG_EXP, &cpu_dev, "Privledged violation UEI\n"); - TRAPME = PRIVVIOL_TRAP; /* set the trap to take */ - if ((CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9)) - TRAPSTATUS |= BIT0; /* set bit 0 of trap status */ - else - TRAPSTATUS |= BIT19; /* set bit 19 of trap status */ - goto newpsd; /* Privlege violation trap */ - } - if (CPUSTATUS & BIT24) { /* see if old mode is blocked */ - irq_pend = 1; /* start scanning interrupts again */ -#ifdef LEAVE_ACTIVE - if (irq_auto) { -/*AIR*/ INTS[irq_auto] &= ~INTS_ACT; /* deactivate specified int level */ -/*AIR*/ SPAD[irq_auto+0x80] &= ~SINT_ACT; /* deactivate in SPAD too */ - sim_debug(DEBUG_IRQ, &cpu_dev, - "<|>IntX deactivate level %02x at UEI PSD1 %08x PSD2 %08x\n", - irq_auto, PSD1, PSD2); -/*AIR*/ irq_auto = 0; /* show done processing in blocked mode */ -/*103020*/ skipinstr = 1; /* skip interrupt test */ - } -#endif - } - CPUSTATUS &= ~BIT24; /* clear status word bit 24 */ - MODES &= ~(BLKMODE|RETMODE);/* reset blocked & retain mode bits */ - PSD2 &= ~(SETBBIT|RETBBIT); /* clear bits 48 & 49 to be unblocked */ - SPAD[0xf5] = PSD2; /* save the current PSD2 */ - SPAD[0xf9] = CPUSTATUS; /* save the cpu status in SPAD */ - break; - case 0x8: /* EAE */ - PSD1 |= AEXPBIT; /* set the enable AEXP flag in PSD */ - CPUSTATUS |= AEXPBIT; /* into status word too */ - MODES |= AEXPBIT; /* enable arithmetic exception in modes & PSD */ - break; - case 0x9: /* RDSTS */ - GPR[reg] = CPUSTATUS; /* get CPU status word */ - sim_debug(DEBUG_CMD, &cpu_dev, - "RDSTS CPUSTATUS %08x SPAD[0xf9] %08x\n", CPUSTATUS, SPAD[0xf9]); - break; - case 0xA: /* SIPU */ /* ignore for now */ - sim_debug(DEBUG_CMD, &cpu_dev, - "SIPU CPUSTATUS %08x SPAD[0xf9] %08x\n", CPUSTATUS, SPAD[0xf9]); - break; - case 0xB: /* RWCS */ /* RWCS ignore for now */ - /* reg = specifies reg containing the ACS/WCS address */ - /* sreg = specifies the ACS/WCS address */ - /* if the WCS option is not present, address spec error */ - /* if the mem addr is not a DW, address spec error */ - /* If 0<-Rs<=fff and Rs bit 0=0, then PROM address */ - /* If 0<-Rs<=fff and Rs bit 0=1, then ACS address */ - /* if bit 20 set, WCS enables, else addr spec error */ - if ((CPUSTATUS & 0x00000800) == 0) { - TRAPME = ADDRSPEC_TRAP; /* bad reg address, error */ - goto newpsd; /* go execute the trap now */ - } - /* Maybe TODO copy something from WCS */ - break; - case 0xC: /* WWCS */ /* WWCS ignore for now */ - /* reg = specifies the logical address in memory that */ - /* is to receive the ACS/WCS contents */ - /* sreg = specifies the ACS/WCS address */ - /* bit 20 of cpu stat must be set=1 to to write to ACS or WCS */ - /* bit 21 of CPU stat must be 0 to write to ACS */ - /* if bit 20 set, WCS enables, else addr spec error */ - if ((CPUSTATUS & 0x00000800) == 0) { - TRAPME = ADDRSPEC_TRAP; /* bad reg address, error */ - goto newpsd; /* go execute the trap now */ - } - /* Maybe TODO copy something to WCS */ - break; - case 0xD: /* SEA */ - if (MODES & BASEBIT) /* see if based */ - goto inv; /* invalid instruction in based mode */ - MODES |= EXTDBIT; /* set new extended flag (bit 5) in modes & PSD */ - PSD1 |= EXTDBIT; /* set the enable AEXP flag in PSD1 */ - CPUSTATUS |= EXTDBIT; /* into status word too */ - break; - case 0xE: /* DAE */ - MODES &= ~AEXPBIT; /* disable arithmetic exception in modes & PSD */ - PSD1 &= ~AEXPBIT; /* disable AEXP flag in PSD */ - CPUSTATUS &= ~AEXPBIT; /* into status word too */ - break; - - case 0xF: /* CEA */ - if (MODES & BASEBIT) /* see if based */ - goto inv; /* invalid instruction in based mode */ - MODES &= ~EXTDBIT; /* disable extended mode in modes and PSD */ - PSD1 &= ~EXTDBIT; /* disable extended mode (bit 5) flag in PSD */ - CPUSTATUS &= ~EXTDBIT; /* into status word too */ - break; + case 0x1: /* WAIT */ + if ((MODES & PRIVBIT) == 0) { /* must be privileged to wait */ + TRAPME = PRIVVIOL_TRAP; /* set the trap to take */ + if ((CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9)) + TRAPSTATUS |= BIT0; /* set bit 0 of trap status */ + else + TRAPSTATUS |= BIT19; /* set bit 19 of trap status */ + goto newpsd; /* Privlege violation trap */ + } + /* if interrupts are blocked, system check trap */ + if (CPUSTATUS & BIT24) { /* status word bit 24 says blocked */ + TRAPME = SYSTEMCHK_TRAP; /* trap condition if F class */ + if ((CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9)) + TRAPSTATUS |= BIT12; /* set bit 0 of trap status */ + else + TRAPSTATUS |= BIT20; /* set bit 20 of trap status */ + goto newpsd; /* system check trap */ + } + if (wait4int == 0) { + time_t result = time(NULL); + sim_debug(DEBUG_DETAIL, &cpu_dev, + "Starting WAIT mode %08x\n", (uint32)result); + } + wait4int = 1; /* show we are waiting for interrupt */ + /* tell simh we will be waiting */ + sim_idle(TMR_RTC, 0); /* wait for next pending device event */ + irq_pend = 1; /* start scanning interrupts again */ + i_flags |= BT; /* keep PC from being incremented while waiting */ + break; + case 0x2: /* NOP */ + break; + case 0x3: /* LCS */ + /* get console switches from memory loc 0x780 */ + if ((TRAPME = Mem_read(0x780, &GPR[reg]))) /* get the word from memory */ + goto newpsd; /* memory read error or map fault */ + set_CCs(GPR[reg], 0); /* set the CC's, CC1 = 0 */ + break; + case 0x4: /* ES */ + if (reg & 1) { /* see if odd reg specified */ + TRAPME = ADDRSPEC_TRAP; /* bad reg address, error */ + goto newpsd; /* go execute the trap now */ + } + /* reg is reg to extend sign into from reg+1 */ + GPR[reg] = (GPR[reg+1] & FSIGN) ? FMASK : 0; + set_CCs(GPR[reg], 0); /* set CCs, CC2 & CC3 */ + break; + case 0x5: /* RND */ + if (reg & 1) { /* see if odd reg specified */ + TRAPME = ADDRSPEC_TRAP; /* bad reg address, error */ + goto newpsd; /* go execute the trap now */ + } + temp = GPR[reg]; /* save the current contents of specified reg */ + t = (temp & FSIGN) != 0; /* set flag for sign bit not set in temp value */ + bc = 1; + t |= ((bc & FSIGN) != 0) ? 2 : 0; /* ditto for the bit value */ + if (GPR[reg+1] & FSIGN) { /* if sign of R+1 is set, incr R by 1 */ + temp += bc; /* add the bit value to the reg */ + /* if both signs are neg and result sign is positive, overflow */ + /* if both signs are pos and result sign is negative, overflow */ + if ((t == 3 && (temp & FSIGN) == 0) || + (t == 0 && (temp & FSIGN) != 0)) { + ovr = 1; /* we have an overflow */ + } + GPR[reg] = temp; /* update the R value */ + } else + ovr = 0; + set_CCs(temp, ovr); /* set the CC's, CC1 = ovr */ + /* the arithmetic exception will be handled */ + /* after instruction is completed */ + /* check for arithmetic exception trap enabled */ + if (ovr && (MODES & AEXPBIT)) { + TRAPME = AEXPCEPT_TRAP; /* set the trap type */ + goto newpsd; /* handle trap */ } break; - case 0x04>>2: /* 0x04 RR|R1|SD|HLF - SD|HLF */ /* ANR, SMC, CMC, RPSWT */ - i_flags &= ~SCC; /* make sure we do not set CC's for dest value */ - switch(opr & 0xF) { - case 0x0: /* ANR */ - dest &= source; /* just an and reg to reg */ - if (dest & MSIGN) - dest |= D32LMASK; /* force upper word to all ones */ - i_flags |= SCC; /* make sure we set CC's for dest value */ - break; + case 0x6: /* BEI */ + if ((MODES & PRIVBIT) == 0) { /* must be privileged to BEI */ + TRAPME = PRIVVIOL_TRAP; /* set the trap to take */ + if ((CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9)) + TRAPSTATUS |= BIT0; /* set bit 0 of trap status */ + else + TRAPSTATUS |= BIT19; /* set bit 19 of trap status */ + goto newpsd; /* Privlege violation trap */ + } + CPUSTATUS |= BIT24; /* into status word bit 24 too */ + PSD2 &= ~(SETBBIT|RETBBIT); /* clear bit 48 & 49 */ + MODES &= ~(BLKMODE|RETMODE); /* reset blocked & retain mode bits */ + PSD2 |= SETBBIT; /* set to blocked state */ + MODES |= BLKMODE; /* set blocked mode */ - case 0xA: /* CMC */ /* Cache Memory Control - Diag use only */ - if (CPU_MODEL == MODEL_87) - break; /* just ignore */ - if (CPU_MODEL < MODEL_67) { - TRAPME = UNDEFINSTR_TRAP; /* Undefined Instruction Trap */ - if ((CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9)) - TRAPSTATUS |= BIT0; /* set bit 0 of trap status */ - goto newpsd; /* handle trap */ - } - if (CPU_MODEL <= MODEL_V6) { - /* Cache memory control bit assignments for reg */ - /* 0-22 reserved, must be zero */ - /* 23 - Initialize Instruction Cache Bank 0 On = 1 Off = 0 */ - /* 24 - Initialize Instruction Cache Bank 1 On = 1 Off = 0 */ - /* 25 - Initialize Operand Cache Bank 0 On = 1 Off = 0 */ - /* 26 - Initialize Operand Cache Bank 1 On = 1 Off = 0 */ - /* 27 - Enable Instruction Cache Bank 0 On = 1 Off = 0 */ - /* 28 - Enable Instruction Cache Bank 1 On = 1 Off = 0 */ - /* 29 - Enable Operand Cache Bank 0 On = 1 Off = 0 */ - /* 30 - Enable Operand Cache Bank 1 On = 1 Off = 0 */ - /* 31 - Bypass Instruction Cache Bank 1 On = 1 Off = 0 */ - sim_debug(DEBUG_EXP, &cpu_dev, - "CMC V6/67 GPR[%02x] = %04x CMCR = %08x CPU STATUS SPAD[f9] = %08x\r\n", - reg, GPR[reg], CMCR, SPAD[0xf9]); - CMCR = GPR[reg]; /* write reg bits 23-31 to cache memory controller */ - i_flags &= ~SD; /* turn off store dest for this instruction */ - } else - if (CPU_MODEL == MODEL_V9) { - sim_debug(DEBUG_EXP, &cpu_dev, - "CMC V9 GPR[%02x] = %08x CMCR = %08x CPU STATUS SPAD[f9] = %08x\r\n", - reg, GPR[reg], CMCR, SPAD[0xf9]); - CMCR = GPR[reg]; /* write reg bits 23-31 to cache memory controller */ - i_flags &= ~SD; /* turn off store dest for this instruction */ - } - break; + SPAD[0xf5] = PSD2; /* save the current PSD2 */ + SPAD[0xf9] = CPUSTATUS; /* save the cpu status in SPAD */ + break; - case 0x7: /* SMC */ /* Shared Memory Control - Diag use only */ - if (CPU_MODEL < MODEL_67) { - TRAPME = UNDEFINSTR_TRAP; /* Undefined Instruction Trap */ - if ((CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9)) - TRAPSTATUS |= BIT0; /* set bit 0 of trap status */ - goto newpsd; /* handle trap */ + case 0x7: /* UEI */ + if ((MODES & PRIVBIT) == 0) { /* must be privileged to UEI */ + TRAPME = PRIVVIOL_TRAP; /* set the trap to take */ + if ((CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9)) + TRAPSTATUS |= BIT0; /* set bit 0 of trap status */ + else + TRAPSTATUS |= BIT19; /* set bit 19 of trap status */ + goto newpsd; /* Privlege violation trap */ + } + if (CPUSTATUS & BIT24) { /* see if old mode is blocked */ + irq_pend = 1; /* start scanning interrupts again */ +#ifdef LEAVE_ACTIVE + if (irq_auto) { +/*AIR*/ INTS[irq_auto] &= ~INTS_ACT; /* deactivate specified int level */ +/*AIR*/ SPAD[irq_auto+0x80] &= ~SINT_ACT; /* deactivate in SPAD too */ + sim_debug(DEBUG_IRQ, &cpu_dev, + "<|>IntX deactivate level %02x at UEI PSD1 %08x PSD2 %08x\n", + irq_auto, PSD1, PSD2); +/*AIR*/ irq_auto = 0; /* show done processing in blocked mode */ + skipinstr = 1; /* skip interrupt test */ } - /* Shared memory control bit assignments for reg */ - /* 0 - Reserved */ - /* 1 - Shared Memory Enabled (=1)/Disabled (=0) */ - /* 2-6 - Upper Bound of Shared Memory */ - /* 7 - Read & Lock Enabled (=1)/Disabled (=0) */ - /* 8-12 - Lower Bound of Shared Memory */ - /* 3-31 - Reserved and must be zero */ -// sim_debug(DEBUG_EXP, &cpu_dev, - sim_debug(DEBUG_CMD, &cpu_dev, - "SMC V6/67 GPR[%02x] = %08x SMCR = %08x CPU STATUS SPAD[f9] = %08x\n", - reg, GPR[reg], SMCR, SPAD[0xf9]); - SMCR = GPR[reg]; /* write reg bits 0-12 to shared memory controller */ +#endif + } + CPUSTATUS &= ~BIT24; /* clear status word bit 24 */ + MODES &= ~(BLKMODE|RETMODE); /* reset blocked & retain mode bits */ + PSD2 &= ~(SETBBIT|RETBBIT); /* clear bits 48 & 49 to be unblocked */ + SPAD[0xf5] = PSD2; /* save the current PSD2 */ + SPAD[0xf9] = CPUSTATUS; /* save the cpu status in SPAD */ + break; + case 0x8: /* EAE */ + PSD1 |= AEXPBIT; /* set the enable AEXP flag in PSD */ + CPUSTATUS |= AEXPBIT; /* into status word too */ + MODES |= AEXPBIT; /* enable arithmetic exception in modes & PSD */ + break; + case 0x9: /* RDSTS */ + GPR[reg] = CPUSTATUS; /* get CPU status word */ + break; + case 0xA: /* SIPU */ /* ignore for now */ + sim_debug(DEBUG_CMD, &cpu_dev, + "SIPU CPUSTATUS %08x SPAD[0xf9] %08x\n", CPUSTATUS, SPAD[0xf9]); + break; + case 0xB: /* RWCS */ /* RWCS ignore for now */ + /* reg = specifies reg containing the ACS/WCS address */ + /* sreg = specifies the ACS/WCS address */ + /* if the WCS option is not present, address spec error */ + /* if the mem addr is not a DW, address spec error */ + /* If 0<-Rs<=fff and Rs bit 0=0, then PROM address */ + /* If 0<-Rs<=fff and Rs bit 0=1, then ACS address */ + /* if bit 20 set, WCS enables, else addr spec error */ + if ((CPUSTATUS & 0x00000800) == 0) { + TRAPME = ADDRSPEC_TRAP; /* bad reg address, error */ + goto newpsd; /* go execute the trap now */ + } + /* Maybe TODO copy something from WCS */ + break; + case 0xC: /* WWCS */ /* WWCS ignore for now */ + /* reg = specifies the logical address in memory that */ + /* is to receive the ACS/WCS contents */ + /* sreg = specifies the ACS/WCS address */ + /* bit 20 of cpu stat must be set=1 to to write to ACS or WCS */ + /* bit 21 of CPU stat must be 0 to write to ACS */ + /* if bit 20 set, WCS enables, else addr spec error */ + if ((CPUSTATUS & 0x00000800) == 0) { + TRAPME = ADDRSPEC_TRAP; /* bad reg address, error */ + goto newpsd; /* go execute the trap now */ + } + /* Maybe TODO copy something to WCS */ + break; + case 0xD: /* SEA */ + if (MODES & BASEBIT) /* see if based */ + goto inv; /* invalid instruction in based mode */ + MODES |= EXTDBIT; /* set new extended flag (bit 5) in modes & PSD */ + PSD1 |= EXTDBIT; /* set the enable AEXP flag in PSD1 */ + CPUSTATUS |= EXTDBIT; /* into status word too */ + break; + case 0xE: /* DAE */ + MODES &= ~AEXPBIT; /* disable arithmetic exception in modes & PSD */ + PSD1 &= ~AEXPBIT; /* disable AEXP flag in PSD */ + CPUSTATUS &= ~AEXPBIT; /* into status word too */ + break; + + case 0xF: /* CEA */ + if (MODES & BASEBIT) /* see if based */ + goto inv; /* invalid instruction in based mode */ + MODES &= ~EXTDBIT; /* disable extended mode in modes and PSD */ + PSD1 &= ~EXTDBIT; /* disable extended mode (bit 5) flag in PSD */ + CPUSTATUS &= ~EXTDBIT; /* into status word too */ + break; + } + break; + case 0x04>>2: /* 0x04 RR|R1|SD|HLF - SD|HLF */ /* ANR, SMC, CMC, RPSWT */ + i_flags &= ~SCC; /* make sure we do not set CC's for dest value */ + switch(opr & 0xF) { + case 0x0: /* ANR */ + dest &= source; /* just an and reg to reg */ + if (dest & MSIGN) + dest |= D32LMASK; /* force upper word to all ones */ + i_flags |= SCC; /* make sure we set CC's for dest value */ + break; + + case 0xA: /* CMC */ /* Cache Memory Control - Diag use only */ + if (CPU_MODEL == MODEL_87) + break; /* just ignore */ + if (CPU_MODEL < MODEL_67) { + TRAPME = UNDEFINSTR_TRAP; /* Undefined Instruction Trap */ + if ((CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9)) + TRAPSTATUS |= BIT0; /* set bit 0 of trap status */ + goto newpsd; /* handle trap */ + } + if (CPU_MODEL <= MODEL_V6) { + /* Cache memory control bit assignments for reg */ + /* 0-22 reserved, must be zero */ + /* 23 - Initialize Instruction Cache Bank 0 On = 1 Off = 0 */ + /* 24 - Initialize Instruction Cache Bank 1 On = 1 Off = 0 */ + /* 25 - Initialize Operand Cache Bank 0 On = 1 Off = 0 */ + /* 26 - Initialize Operand Cache Bank 1 On = 1 Off = 0 */ + /* 27 - Enable Instruction Cache Bank 0 On = 1 Off = 0 */ + /* 28 - Enable Instruction Cache Bank 1 On = 1 Off = 0 */ + /* 29 - Enable Operand Cache Bank 0 On = 1 Off = 0 */ + /* 30 - Enable Operand Cache Bank 1 On = 1 Off = 0 */ + /* 31 - Bypass Instruction Cache Bank 1 On = 1 Off = 0 */ + sim_debug(DEBUG_EXP, &cpu_dev, + "CMC V6/67 GPR[%02x] = %04x CMCR = %08x CPU STATUS SPAD[f9] = %08x\r\n", + reg, GPR[reg], CMCR, SPAD[0xf9]); + CMCR = GPR[reg]; /* write reg bits 23-31 to cache memory controller */ i_flags &= ~SD; /* turn off store dest for this instruction */ - break; + } else + if (CPU_MODEL == MODEL_V9) { + sim_debug(DEBUG_EXP, &cpu_dev, + "CMC V9 GPR[%02x] = %08x CMCR = %08x CPU STATUS SPAD[f9] = %08x\r\n", + reg, GPR[reg], CMCR, SPAD[0xf9]); + CMCR = GPR[reg]; /* write reg bits 23-31 to cache memory controller */ + i_flags &= ~SD; /* turn off store dest for this instruction */ + } + break; + + case 0x7: /* SMC */ /* Shared Memory Control - Diag use only */ + if (CPU_MODEL < MODEL_67) { + TRAPME = UNDEFINSTR_TRAP; /* Undefined Instruction Trap */ + if ((CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9)) + TRAPSTATUS |= BIT0; /* set bit 0 of trap status */ + goto newpsd; /* handle trap */ + } + /* Shared memory control bit assignments for reg */ + /* 0 - Reserved */ + /* 1 - Shared Memory Enabled (=1)/Disabled (=0) */ + /* 2-6 - Upper Bound of Shared Memory */ + /* 7 - Read & Lock Enabled (=1)/Disabled (=0) */ + /* 8-12 - Lower Bound of Shared Memory */ + /* 3-31 - Reserved and must be zero */ +// sim_debug(DEBUG_EXP, &cpu_dev, + sim_debug(DEBUG_CMD, &cpu_dev, + "SMC V6/67 GPR[%02x] = %08x SMCR = %08x CPU STATUS SPAD[f9] = %08x\n", + reg, GPR[reg], SMCR, SPAD[0xf9]); + SMCR = GPR[reg]; /* write reg bits 0-12 to shared memory controller */ + i_flags &= ~SD; /* turn off store dest for this instruction */ + break; /* 67, 97, V6 Computer Configuration Word is copied when bit zero of Rd set to one (0x80000000) */ /* |-----------+-----------+-----------+-----------+-----------+-----------+-----------+-----------| */ @@ -2934,810 +2936,347 @@ exec: /* */ /* When bit zero of Rd is zero, PSW word 2 is copies to Rd (0x00000000) */ /* */ - case 0xB: /* RPSWT */ /* Read Processor Status Word 2 (PSD2) */ - if ((GPR[reg] & 0x80000000) && (CPU_MODEL < MODEL_V9)) { - /* if bit 0 of reg set, return (default 0) CPU Configuration Word */ - dest = CCW; /* no cache or shared memory */ -//NO WCS dest |= 0x0000c000; /* set SIM bit for DIAGS */ - /* make sure bit 19 is zero saying IPU not present */ - dest &= ~0x00001000; /* reset IPU bit for DIAGS */ - /* bit 22 set for access ECO present */ - dest |= 0x00000200; /* set ECO bit for DIAGS */ - /* Try setting cache on bits 27-31 */ - dest |= 0x0000001f; /* set SIM bit for DIAGS */ - } else - if ((GPR[reg] & 0x80000000) && (CPU_MODEL == MODEL_V9)) { - /* if bit 0 of reg set, return Cache/Shadow Configuration Word */ - CMSMC = 0xffff0000; /* no CPU/IPU Cache/Shadow unit present */ - CMSMC |= 0x00000000; /* CPU Cache/Shadow unit present */ - CMSMC |= 0x00000800; /* bit 20, IPU not present */ - CMSMC |= 0x00000200; /* bit 22, Access Protection ECO present */ - CMSMC |= 0x0000001f; /* CPU Firmware Version 1/Rev level 0 */ - dest = CMSMC; /* return starus */ - } else - if ((GPR[reg] & 0x40000000) && (CPU_MODEL == MODEL_V9)) { - /* if bit 1 of reg set, return CPU Shadow Memory Configuration Word */ - CSMCW = 0x00000000; /* no Shadow unit present */ - dest = CSMCW; /* return starus */ - } else - if ((GPR[reg] & 0x20000000) && (CPU_MODEL == MODEL_V9)) { - /* if bit 2 of reg set, return Cache Memory Configuration Word */ - ISMCW = 0x00000000; /* no Shadow unit present */ - dest = ISMCW; /* return starus */ - } else - if ((GPR[reg] & BIT0) == 0x00000000) { - /* if bit 0 of reg not set, return PSD2 */ - /* make sure bit 49 (block state is current state */ - dest = SPAD[0xf5]; /* get PSD2 for user from SPAD 0xf5 */ - dest &= ~(SETBBIT|RETBBIT); /* clear bit 48 & 49 to be unblocked */ - if (CPUSTATUS & BIT24) { /* see if old mode is blocked */ - dest |= SETBBIT; /* set bit 49 for blocked */ - } + case 0xB: /* RPSWT */ /* Read Processor Status Word 2 (PSD2) */ + if ((GPR[reg] & 0x80000000) && (CPU_MODEL < MODEL_V9)) { + /* if bit 0 of reg set, return (default 0) CPU Configuration Word */ + dest = CCW; /* no cache or shared memory */ + /* make sure bit 19 is zero saying IPU not present */ + dest &= ~0x00001000; /* reset IPU bit for DIAGS */ + /* bit 22 set for access ECO present */ + dest |= 0x00000200; /* set ECO bit for DIAGS */ + /* Try setting cache on bits 27-31 */ + dest |= 0x0000001f; /* set SIM bit for DIAGS */ + } else + if ((GPR[reg] & 0x80000000) && (CPU_MODEL == MODEL_V9)) { + /* if bit 0 of reg set, return Cache/Shadow Configuration Word */ + CMSMC = 0xffff0000; /* no CPU/IPU Cache/Shadow unit present */ + CMSMC |= 0x00000000; /* CPU Cache/Shadow unit present */ + CMSMC |= 0x00000800; /* bit 20, IPU not present */ + CMSMC |= 0x00000200; /* bit 22, Access Protection ECO present */ + CMSMC |= 0x0000001f; /* CPU Firmware Version 1/Rev level 0 */ + dest = CMSMC; /* return starus */ + } else + if ((GPR[reg] & 0x40000000) && (CPU_MODEL == MODEL_V9)) { + /* if bit 1 of reg set, return CPU Shadow Memory Configuration Word */ + CSMCW = 0x00000000; /* no Shadow unit present */ + dest = CSMCW; /* return starus */ + } else + if ((GPR[reg] & 0x20000000) && (CPU_MODEL == MODEL_V9)) { + /* if bit 2 of reg set, return Cache Memory Configuration Word */ + ISMCW = 0x00000000; /* no Shadow unit present */ + dest = ISMCW; /* return starus */ + } else + if ((GPR[reg] & BIT0) == 0x00000000) { + /* if bit 0 of reg not set, return PSD2 */ + /* make sure bit 49 (block state is current state */ + dest = SPAD[0xf5]; /* get PSD2 for user from SPAD 0xf5 */ + dest &= ~(SETBBIT|RETBBIT); /* clear bit 48 & 49 to be unblocked */ + if (CPUSTATUS & BIT24) { /* see if old mode is blocked */ + dest |= SETBBIT; /* set bit 49 for blocked */ } - break; - - case 0x08: /* 0x0408 INV (Diag Illegal instruction) */ - /* HACK HACK HACK for DIAGS */ - if (CPU_MODEL <= MODEL_27) { /* DIAG error for 32/27 only */ - if ((PSD1 & 2) == 0) /* if lf hw instruction */ - i_flags |= HLF; /* if nop in rt hw, bump pc a word */ - } - /* drop through */ - default: /* INV */ /* everything else is invalid instruction */ - TRAPME = UNDEFINSTR_TRAP; /* Undefined Instruction Trap */ - if ((CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9)) - TRAPSTATUS |= BIT0; /* set bit 0 of trap status */ - goto newpsd; /* handle trap */ - break; } break; - case 0x08>>2: /* 0x08 SCC|RR|R1|SD|HLF - */ /* ORR or ORRM */ - dest |= source; /* or the regs into dest reg */ - switch(opr & 0x0f) { - case 0x8: /* this is ORRM op */ - dest &= GPR[4]; /* mask with reg 4 contents */ - /* drop thru */ - case 0x0: /* this is ORR op */ - if (dest & MSIGN) /* see if we need to sign extend */ - dest |= D32LMASK; /* force upper word to all ones */ - break; - default: /* INV */ /* everything else is invalid instruction */ - TRAPME = UNDEFINSTR_TRAP; /* Undefined Instruction Trap */ - if ((CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9)) - TRAPSTATUS |= BIT0; /* set bit 0 of trap status */ - goto newpsd; /* handle trap */ + case 0x08: /* 0x0408 INV (Diag Illegal instruction) */ + /* HACK HACK HACK for DIAGS */ + if (CPU_MODEL <= MODEL_27) { /* DIAG error for 32/27 only */ + if ((PSD1 & 2) == 0) /* if lf hw instruction */ + i_flags |= HLF; /* if nop in rt hw, bump pc a word */ } + /* drop through */ + default: /* INV */ /* everything else is invalid instruction */ + TRAPME = UNDEFINSTR_TRAP; /* Undefined Instruction Trap */ + if ((CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9)) + TRAPSTATUS |= BIT0; /* set bit 0 of trap status */ + goto newpsd; /* handle trap */ break; + } + break; - case 0x0C>>2: /* 0x0c SCC|RR|R1|SD|HLF - SCC|SD|HLF */ /* EOR or EORM */ - dest ^= source; /* exclusive or the regs into dest reg */ - switch(opr & 0x0f) { - case 0x8: /* this is EORM op */ - dest &= GPR[4]; /* mask with reg 4 contents */ - /* drop thru */ - case 0x0: /* this is EOR op */ - if (dest & MSIGN) /* see if we need to sign extend */ - dest |= D32LMASK; /* force upper word to all ones */ - break; - default: /* INV */ /* everything else is invalid instruction */ - TRAPME = UNDEFINSTR_TRAP; /* Undefined Instruction Trap */ - if ((CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9)) - TRAPSTATUS |= BIT0; /* set bit 0 of trap status */ - goto newpsd; /* handle trap */ - } + case 0x08>>2: /* 0x08 SCC|RR|R1|SD|HLF - */ /* ORR or ORRM */ + dest |= source; /* or the regs into dest reg */ + switch(opr & 0x0f) { + case 0x8: /* this is ORRM op */ + dest &= GPR[4]; /* mask with reg 4 contents */ + /* drop thru */ + case 0x0: /* this is ORR op */ + if (dest & MSIGN) /* see if we need to sign extend */ + dest |= D32LMASK; /* force upper word to all ones */ break; + default: /* INV */ /* everything else is invalid instruction */ + TRAPME = UNDEFINSTR_TRAP; /* Undefined Instruction Trap */ + if ((CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9)) + TRAPSTATUS |= BIT0; /* set bit 0 of trap status */ + goto newpsd; /* handle trap */ + } + break; - case 0x10>>2: /* 0x10 HLF - HLF */ /* CAR or (basemode SACZ ) */ - if ((opr & 0xF) == 0) { /* see if CAR instruction */ - /* handle non basemode/basemode CAR instr */ - if ((int32)GPR[reg] < (int32)GPR[sreg]) - CC = CC3BIT; /* Rd < Rs; negative */ - else - if (GPR[reg] == GPR[sreg]) - CC = CC4BIT; /* Rd == Rs; zero */ - else - CC = CC2BIT; /* Rd > Rs; positive */ - PSD1 &= 0x87FFFFFE; /* clear the old CC's */ - PSD1 |= (CC & 0x78000000); /* update the CC's in the PSD */ - } else { - if ((MODES & BASEBIT) == 0) { /* if not basemode, error */ - if ((CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9)) - TRAPSTATUS |= BIT0; /* set bit 0 of trap status */ - TRAPME = UNDEFINSTR_TRAP; /* Undefined Instruction Trap */ - goto newpsd; /* handle trap */ - } - /* handle basemode SACZ instruction */ -sacz: /* non basemode SCZ enters here */ - temp = GPR[reg]; /* get destination reg contents to shift */ - CC = 0; /* zero the CC's */ - t = 0; /* start with zero shift count */ - if (temp == 0) { - CC = CC4BIT; /* set CC4 showing dest is zero & cnt is zero too */ - } -#ifdef NOT_FOR_DIAG - /* The doc says the reg is not shifted if bit 0 is set on entry. */ - /* diags says it does, so that is what we will do */ - /* set count to zero, but shift reg 1 left */ - else - if (temp & BIT0) { - CC = 0; /* clear CC4 & set count to zero */ - } -#endif - else - if (temp != 0) { /* shift non zero values */ - while ((temp & FSIGN) == 0) { /* shift the reg until bit 0 is set */ - temp <<= 1; /* shift left 1 bit */ - t++; /* increment shift count */ - } - temp <<= 1; /* shift the sign bit out */ - } - GPR[reg] = temp; /* save the shifted values */ - GPR[sreg] = t; /* set the shift cnt into the src reg */ - PSD1 &= 0x87FFFFFE; /* clear the old CC's */ - PSD1 |= (CC & 0x78000000); /* update the CC's in the PSD */ - } + case 0x0C>>2: /* 0x0c SCC|RR|R1|SD|HLF - SCC|SD|HLF */ /* EOR or EORM */ + dest ^= source; /* exclusive or the regs into dest reg */ + switch(opr & 0x0f) { + case 0x8: /* this is EORM op */ + dest &= GPR[4]; /* mask with reg 4 contents */ + /* drop thru */ + case 0x0: /* this is EOR op */ + if (dest & MSIGN) /* see if we need to sign extend */ + dest |= D32LMASK; /* force upper word to all ones */ break; + default: /* INV */ /* everything else is invalid instruction */ + TRAPME = UNDEFINSTR_TRAP; /* Undefined Instruction Trap */ + if ((CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9)) + TRAPSTATUS |= BIT0; /* set bit 0 of trap status */ + goto newpsd; /* handle trap */ + } + break; - case 0x14>>2: /* 0x14 HLF - HLF */ /* CMR compare masked with reg */ - if (opr & 0xf) { /* any subop not zero is error */ - TRAPME = UNDEFINSTR_TRAP; /* Undefined Instruction Trap */ - if ((CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9)) - TRAPSTATUS |= BIT0; /* set bit 0 of trap status */ - goto newpsd; /* handle trap */ - } - temp = GPR[reg] ^ GPR[sreg]; /* exclusive or src and destination values */ - temp &= GPR[4]; /* and with mask reg (GPR 4) */ - CC = 0; /* set all CCs zero */ - if (temp == 0) /* if result is zero, set CC4 */ - CC = CC4BIT; /* set CC4 to show result 0 */ + case 0x10>>2: /* 0x10 HLF - HLF */ /* CAR or (basemode SACZ ) */ + if ((opr & 0xF) == 0) { /* see if CAR instruction */ + /* handle non basemode/basemode CAR instr */ + if ((int32)GPR[reg] < (int32)GPR[sreg]) + CC = CC3BIT; /* Rd < Rs; negative */ + else + if (GPR[reg] == GPR[sreg]) + CC = CC4BIT; /* Rd == Rs; zero */ + else + CC = CC2BIT; /* Rd > Rs; positive */ PSD1 &= 0x87FFFFFE; /* clear the old CC's */ PSD1 |= (CC & 0x78000000); /* update the CC's in the PSD */ - break; + } else { + if ((MODES & BASEBIT) == 0) { /* if not basemode, error */ + if ((CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9)) + TRAPSTATUS |= BIT0; /* set bit 0 of trap status */ + TRAPME = UNDEFINSTR_TRAP; /* Undefined Instruction Trap */ + goto newpsd; /* handle trap */ + } + /* handle basemode SACZ instruction */ +sacz: /* non basemode SCZ enters here */ + temp = GPR[reg]; /* get destination reg contents to shift */ + CC = 0; /* zero the CC's */ + t = 0; /* start with zero shift count */ + if (temp == 0) { + CC = CC4BIT; /* set CC4 showing dest is zero & cnt is zero too */ + } +#ifdef NOT_FOR_DIAG + /* The doc says the reg is not shifted if bit 0 is set on entry. */ + /* diags says it does, so that is what we will do */ + /* set count to zero, but shift reg 1 left */ + else + if (temp & BIT0) { + CC = 0; /* clear CC4 & set count to zero */ + } +#endif + else + if (temp != 0) { /* shift non zero values */ + while ((temp & FSIGN) == 0) { /* shift the reg until bit 0 is set */ + temp <<= 1; /* shift left 1 bit */ + t++; /* increment shift count */ + } + temp <<= 1; /* shift the sign bit out */ + } + GPR[reg] = temp; /* save the shifted values */ + GPR[sreg] = t; /* set the shift cnt into the src reg */ + PSD1 &= 0x87FFFFFE; /* clear the old CC's */ + PSD1 |= (CC & 0x78000000); /* update the CC's in the PSD */ + } + break; - case 0x18>>2: /* 0x18 HLF - HLF */ /* SBR, (basemode ZBR, ABR, TBR */ - if (MODES & BASEBIT) { /* handle basemode ZBR, ABR, TBR */ - if ((opr & 0xC) == 0x0) /* SBR instruction */ - goto sbr; /* use nonbase SBR code */ - if ((opr & 0xC) == 0x4) /* ZBR instruction */ - goto zbr; /* use nonbase ZBR code */ - if ((opr & 0xC) == 0x8) /* ABR instruction */ - goto abr; /* use nonbase ABR code */ - if ((opr & 0xC) == 0xC) /* TBR instruction */ - goto tbr; /* use nonbase TBR code */ + case 0x14>>2: /* 0x14 HLF - HLF */ /* CMR compare masked with reg */ + if (opr & 0xf) { /* any subop not zero is error */ + TRAPME = UNDEFINSTR_TRAP; /* Undefined Instruction Trap */ + if ((CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9)) + TRAPSTATUS |= BIT0; /* set bit 0 of trap status */ + goto newpsd; /* handle trap */ + } + temp = GPR[reg] ^ GPR[sreg]; /* exclusive or src and destination values */ + temp &= GPR[4]; /* and with mask reg (GPR 4) */ + CC = 0; /* set all CCs zero */ + if (temp == 0) /* if result is zero, set CC4 */ + CC = CC4BIT; /* set CC4 to show result 0 */ + PSD1 &= 0x87FFFFFE; /* clear the old CC's */ + PSD1 |= (CC & 0x78000000); /* update the CC's in the PSD */ + break; + + case 0x18>>2: /* 0x18 HLF - HLF */ /* SBR, (basemode ZBR, ABR, TBR */ + if (MODES & BASEBIT) { /* handle basemode ZBR, ABR, TBR */ + if ((opr & 0xC) == 0x0) /* SBR instruction */ + goto sbr; /* use nonbase SBR code */ + if ((opr & 0xC) == 0x4) /* ZBR instruction */ + goto zbr; /* use nonbase ZBR code */ + if ((opr & 0xC) == 0x8) /* ABR instruction */ + goto abr; /* use nonbase ABR code */ + if ((opr & 0xC) == 0xC) /* TBR instruction */ + goto tbr; /* use nonbase TBR code */ inv: + TRAPME = UNDEFINSTR_TRAP; /* Undefined Instruction Trap */ + if ((CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9)) + TRAPSTATUS |= BIT0; /* set bit 0 of trap status */ + goto newpsd; /* handle trap */ + + } else { /* handle non basemode SBR */ + if (opr & 0xc) { /* any subop not zero is error */ TRAPME = UNDEFINSTR_TRAP; /* Undefined Instruction Trap */ if ((CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9)) TRAPSTATUS |= BIT0; /* set bit 0 of trap status */ goto newpsd; /* handle trap */ - - } else { /* handle non basemode SBR */ - if (opr & 0xc) { /* any subop not zero is error */ - TRAPME = UNDEFINSTR_TRAP; /* Undefined Instruction Trap */ - if ((CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9)) - TRAPSTATUS |= BIT0; /* set bit 0 of trap status */ - goto newpsd; /* handle trap */ - } + } sbr: /* handle basemode too */ - /* move the byte field bits 14-15 to bits 27-28 */ - /* or in the bit# from dest reg field bits 6-8 into bit 29-31 */ - bc = (((opr << 3) & 0x18) | reg); /* get # bits to shift right */ - bc = BIT0 >> bc; /* make a bit mask of bit number */ - t = (PSD1 & 0x70000000) >> 1; /* get old CC bits 1-3 into CCs 2-4*/ - PSD1 &= 0x87FFFFFE; /* clear the old CC's */ - if (GPR[sreg] & bc) /* test the bit in src reg */ - t |= CC1BIT; /* set CC1 to the bit value */ - GPR[sreg] |= bc; /* set the bit in src reg */ - PSD1 |= t; /* update the CC's in the PSD */ - } - break; + /* move the byte field bits 14-15 to bits 27-28 */ + /* or in the bit# from dest reg field bits 6-8 into bit 29-31 */ + bc = (((opr << 3) & 0x18) | reg); /* get # bits to shift right */ + bc = BIT0 >> bc; /* make a bit mask of bit number */ + t = (PSD1 & 0x70000000) >> 1; /* get old CC bits 1-3 into CCs 2-4*/ + PSD1 &= 0x87FFFFFE; /* clear the old CC's */ + if (GPR[sreg] & bc) /* test the bit in src reg */ + t |= CC1BIT; /* set CC1 to the bit value */ + GPR[sreg] |= bc; /* set the bit in src reg */ + PSD1 |= t; /* update the CC's in the PSD */ + } + break; - case 0x1C>>2: /* 0x1C HLF - HLF */ /* ZBR (basemode SRA, SRL, SLA, SLL) */ - if (MODES & BASEBIT) { /* handle basemode SRA, SRL, SLA, SLL */ - bc = opr & 0x1f; /* get bit shift count */ - if ((opr & 0x60) == 0x00) { /* SRA instruction */ - temp = GPR[reg]; /* get reg value to shift */ - t = temp & FSIGN; /* sign value */ - for (ix=0; ix>= 1; /* shift bit 0 right one bit */ - temp |= t; /* restore original sign bit */ - } - GPR[reg] = temp; /* save the new value */ - break; - } - if ((opr & 0x60) == 0x20) { /* SRL instruction */ - GPR[reg] >>= bc; /* value to be output */ - break; - } - if ((opr & 0x60) == 0x40) { /* SLA instruction */ - temp = GPR[reg]; /* get reg value to shift */ - t = temp & FSIGN; /* sign value */ - ovr = 0; /* set ovr off */ - for (ix=0; ix>2: /* 0x1C HLF - HLF */ /* ZBR (basemode SRA, SRL, SLA, SLL) */ + if (MODES & BASEBIT) { /* handle basemode SRA, SRL, SLA, SLL */ + bc = opr & 0x1f; /* get bit shift count */ + if ((opr & 0x60) == 0x00) { /* SRA instruction */ + temp = GPR[reg]; /* get reg value to shift */ + t = temp & FSIGN; /* sign value */ + for (ix=0; ix>= 1; /* shift bit 0 right one bit */ temp |= t; /* restore original sign bit */ - GPR[reg] = temp; /* save the new value */ - PSD1 &= 0x87FFFFFE; /* clear the old CC's */ - if (ovr) - PSD1 |= BIT1; /* CC1 in PSD */ - /* the arithmetic exception will be handled */ - /* after instruction is completed */ - /* check for arithmetic exception trap enabled */ - if (ovr && (MODES & AEXPBIT)) { - TRAPME = AEXPCEPT_TRAP; /* set the trap type */ - goto newpsd; /* go execute the trap now */ - } - break; - } - if ((opr & 0x60) == 0x60) { /* SLL instruction */ - GPR[reg] <<= bc; /* value to be output */ - break; } + GPR[reg] = temp; /* save the new value */ break; - } else { /* handle nonbase ZBR */ - if (opr & 0xc) { /* any subop not zero is error */ - TRAPME = UNDEFINSTR_TRAP; /* Undefined Instruction Trap */ - if ((CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9)) - TRAPSTATUS |= BIT0; /* set bit 0 of trap status */ - goto newpsd; /* handle trap */ - } -zbr: /* handle basemode too */ - /* move the byte field bits 14-15 to bits 27-28 */ - /* or in the bit# from dest reg field bits 6-8 into bit 29-31 */ - bc = (((opr << 3) & 0x18) | reg); /* get # bits to shift right */ - bc = BIT0 >> bc; /* make a bit mask of bit number */ - t = (PSD1 & 0x70000000) >> 1; /* get old CC bits 1-3 into CCs 2-4*/ - PSD1 &= 0x87FFFFFE; /* clear the old CC's */ - if (GPR[sreg] & bc) /* test the bit in src reg */ - t |= CC1BIT; /* set CC1 to the bit value */ - GPR[sreg] &= ~bc; /* reset the bit in src reg */ - PSD1 |= t; /* update the CC's in the PSD */ } - break; - - case 0x20>>2: /* 0x20 HLF - HLF */ /* ABR (basemode SRAD, SRLD, SLAD, SLLD) */ - if (MODES & BASEBIT) { /* handle basemode SRAD, SRLD, SLAD, SLLD */ - if (reg & 1) { /* see if odd reg specified */ - TRAPME = ADDRSPEC_TRAP; /* bad reg address, error */ - goto newpsd; /* go execute the trap now */ - } - dest = (t_uint64)GPR[reg+1]; /* get low order reg value */ - dest |= (((t_uint64)GPR[reg]) << 32); /* insert upper reg value */ - bc = opr & 0x1f; /* get bit shift count */ - source = dest & DMSIGN; /* 64 bit sign value */ - switch (opr & 0x60) { - case 0x00: /* SRAD instruction */ - for (ix=0; ix>= 1; /* shift bit 0 right one bit */ - dest |= source; /* restore original sign bit */ - } - break; - - case 0x20: /* SRLD */ - dest >>= bc; /* shift right #bits */ - break; - - case 0x40: /* SLAD instruction */ - ovr = 0; /* set ovr off */ - for (ix=0; ix>32) & FMASK);/* save the hi order reg */ - PSD1 &= 0x87FFFFFE; /* clear the old CC's */ - if (ovr) - PSD1 |= BIT1; /* CC1 in PSD */ - /* the arithmetic exception will be handled */ - /* after instruction is completed */ - /* check for arithmetic exception trap enabled */ - if (ovr && (MODES & AEXPBIT)) { - TRAPME = AEXPCEPT_TRAP; /* set the trap type */ - goto newpsd; /* go execute the trap now */ - } - break; - - case 0x60: /* SLLD */ - dest <<= bc; /* shift left #bits */ - break; - } - GPR[reg+1] = (uint32)(dest & FMASK); /* save the low order reg */ - GPR[reg] = (uint32)((dest>>32) & FMASK);/* save the hi order reg */ + if ((opr & 0x60) == 0x20) { /* SRL instruction */ + GPR[reg] >>= bc; /* value to be output */ break; - - } else { /* handle nonbase mode ABR */ - if (opr & 0xc) { /* any subop not zero is error */ - TRAPME = UNDEFINSTR_TRAP; /* Undefined Instruction Trap */ - if ((CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9)) - TRAPSTATUS |= BIT0; /* set bit 0 of trap status */ - goto newpsd; /* handle trap */ + } + if ((opr & 0x60) == 0x40) { /* SLA instruction */ + temp = GPR[reg]; /* get reg value to shift */ + t = temp & FSIGN; /* sign value */ + ovr = 0; /* set ovr off */ + for (ix=0; ix> bc; /* make a bit mask of bit number */ - temp = GPR[sreg]; /* get reg value to add bit to */ - t = (temp & FSIGN) != 0; /* set flag for sign bit not set in temp value */ - t |= ((bc & FSIGN) != 0) ? 2 : 0; /* ditto for the bit value */ - temp += bc; /* add the bit value to the reg */ - /* if both signs are neg and result sign is positive, overflow */ - /* if both signs are pos and result sign is negative, overflow */ - if ((t == 3 && (temp & FSIGN) == 0) || - (t == 0 && (temp & FSIGN) != 0)) { - ovr = 1; /* we have an overflow */ - } - GPR[sreg] = temp; /* save the new value */ - set_CCs(temp, ovr); /* set the CC's, CC1 = ovr */ + temp &= ~BIT0; /* clear sign bit */ + temp |= t; /* restore original sign bit */ + GPR[reg] = temp; /* save the new value */ + PSD1 &= 0x87FFFFFE; /* clear the old CC's */ + if (ovr) + PSD1 |= BIT1; /* CC1 in PSD */ /* the arithmetic exception will be handled */ /* after instruction is completed */ /* check for arithmetic exception trap enabled */ if (ovr && (MODES & AEXPBIT)) { TRAPME = AEXPCEPT_TRAP; /* set the trap type */ - goto newpsd; /* handle trap */ + goto newpsd; /* go execute the trap now */ } + break; + } + if ((opr & 0x60) == 0x60) { /* SLL instruction */ + GPR[reg] <<= bc; /* value to be output */ + break; } break; - - case 0x24>>2: /* 0x24 HLF - HLF */ /* TBR (basemode SRC) */ - if (MODES & BASEBIT) { /* handle SRC basemode */ - bc = opr & 0x1f; /* get bit shift count */ - temp = GPR[reg]; /* get reg value to shift */ - if ((opr & 0x60) == 0x40) { /* SLC instruction */ - for (ix=0; ix>= 1; /* shift the bit out */ - if (t) - temp |= BIT0; /* put in new sign bit */ - } - } - GPR[reg] = temp; /* shift result */ - } else { /* handle TBR non basemode */ - if (opr & 0xc) { /* any subop not zero is error */ - TRAPME = UNDEFINSTR_TRAP; /* Undefined Instruction Trap */ - if ((CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9)) - TRAPSTATUS |= BIT0; /* set bit 0 of trap status */ - goto newpsd; /* handle trap */ - } -tbr: /* handle basemode TBR too */ - /* move the byte field bits 14-15 to bits 27-28 */ - /* or in the bit# from dest reg field bits 6-8 into bit 29-31 */ - bc = (((opr << 3) & 0x18) | reg); /* get # bits to shift right */ - bc = BIT0 >> bc; /* make a bit mask of bit number */ - t = (PSD1 & 0x70000000) >> 1; /* get old CC bits 1-3 into CCs 2-4*/ - PSD1 &= 0x87FFFFFE; /* clear the old CC's */ - if (GPR[sreg] & bc) /* test the bit in src reg */ - t |= CC1BIT; /* set CC1 to the bit value */ - PSD1 |= t; /* update the CC's in the PSD */ - } - break; - - case 0x28>>2: /* 0x28 HLF - HLF */ /* Misc OP REG instructions */ - switch(opr & 0xF) { - - case 0x0: /* TRSW */ - if (MODES & BASEBIT) - temp = 0x78FFFFFE; /* bits 1-4 and 24 bit addr for based mode */ - else - temp = 0x7807FFFE; /* bits 1-4 and 19 bit addr for non based mode */ - addr = GPR[reg]; /* get reg value */ - /* we are returning to the addr in reg, set CC's from reg */ - /* update the PSD with new address from reg */ - PSD1 &= ~temp; /* clean the bits to be changed */ - PSD1 |= (addr & temp); /* insert the CC's and address */ - sim_debug(DEBUG_DETAIL, &cpu_dev, - "TRSW REG %01x PSD %08x %08x modes %08x temp %06x\n", - reg, PSD1, PSD2, MODES, temp); - i_flags |= BT; /* we branched, so no PC update */ - break; - - case 0x2: /* XCBR */ /* Exchange base registers */ - if ((MODES & BASEBIT) == 0) /* see if nonbased */ - goto inv; /* invalid instruction in nonbased mode */ - temp = BR[reg]; /* get dest reg value */ - BR[reg] = BR[sreg]; /* put source reg value int dest reg */ - BR[sreg] = temp; /* put dest reg value into src reg */ - break; - - case 0x4: /* TCCR */ /* Transfer condition codes to GPR bits 28-31 */ - if ((MODES & BASEBIT) == 0) /* see if nonbased */ - goto inv; /* invalid instruction in nonbased mode */ - temp = CC >> 27; /* right justify CC's in reg */ - GPR[reg] = temp; /* put dest reg value into src reg */ - break; - - case 0x5: /* TRCC */ /* Transfer GPR bits 28-31 to condition codes */ - if ((MODES & BASEBIT) == 0) /* see if nonbased */ - goto inv; /* invalid instruction in nonbased mode */ - PSD1 = ((PSD1 & 0x87fffffe) | ((GPR[reg] & 0xf) << 27)); /* insert CCs from reg */ -// sim_debug(DEBUG_EXP, &cpu_dev, -// "TRCC REG %01x PSD %08x %08x modes %08x temp %06x\n", -// reg, PSD1, PSD2, MODES, GPR[reg]); - break; - - case 0x8: /* BSUB */ /* Procedure call */ - if ((MODES & BASEBIT) == 0) /* see if nonbased */ - goto inv; /* invalid instruction in nonbased mode */ - - /* if Rd field is 0 (reg is b6-b8), this is a BSUB instruction */ - /* otherwise it is a CALL instruction (Rd != 0) */ - if (reg == 0) { - /* BSUB instruction */ - uint32 cfp = BR[2]; /* get dword bounded frame pointer from BR2 */ - if ((BR[2] & 0x7) != 0) { - /* Fault, must be dw bounded address */ - TRAPME = ADDRSPEC_TRAP; /* bad address, error */ - goto newpsd; /* go execute the trap now */ - } - cfp = BR[2] & 0x00fffff8; /* clean the cfp address to 24 bit dw */ - - M[cfp>>2] = (PSD1 + 2) & 0x01fffffe; /* save AEXP bit and PC into frame */ - M[(cfp>>2)+1] = 0x80000000; /* show frame created by BSUB instr */ - BR[1] = BR[sreg] & MASK24; /* Rs reg to BR 1 */ - PSD1 = (PSD1 & 0xff000000) | (BR[1] & MASK24); /* New PSD address */ - BR[3] = GPR[0]; /* GPR 0 to BR 3 (AP) */ - BR[0] = cfp; /* set frame pointer from BR 2 into BR 0 */ - i_flags |= BT; /* we changed the PC, so no PC update */ - } else - - { - /* CALL instruction */ - /* get frame pointer from BR2-16 words & make it a dword addr */ - uint32 cfp = ((BR[2]-0x40) & 0x00fffff8); - - /* if cfp and cfp+15w are in different maps, then addr exception error */ - if ((cfp & 0xffe000) != ((cfp+0x3f) & 0xffe000)) { - TRAPME = ADDRSPEC_TRAP; /* bad reg address, error */ - goto newpsd; /* go execute the trap now */ - } - - temp = (PSD1+2) & 0x01fffffe; /* save AEXP bit and PC from PSD1 in to frame */ - if ((TRAPME = Mem_write(cfp, &temp))) { /* Save the PSD into memory */ - goto newpsd; /* memory write error or map fault */ - } - - temp = 0x00000000; /* show frame created by CALL instr */ - if ((TRAPME = Mem_write(cfp+4, &temp))) { /* Save zero into memory */ - goto newpsd; /* memory write error or map fault */ - } - - /* Save BR 0-7 to stack */ - for (ix=0; ix<8; ix++) { - if ((TRAPME = Mem_write(cfp+(4*ix)+8, &BR[ix]))) { /* Save into memory */ - goto newpsd; /* memory write error or map fault */ - } - } - - /* save GPR 2-8 to stack */ - for (ix=2; ix<8; ix++) { - if ((TRAPME = Mem_write(cfp+(4*ix)+32, &GPR[ix]))) { /* Save into memory */ - goto newpsd; /* memory write error or map fault */ - } - } - - /* keep bits 0-7 from old PSD */ - PSD1 = (PSD1 & 0xff000000) | ((BR[sreg]) & MASK24); /* New PSD address */ - BR[1] = BR[sreg]; /* Rs reg to BR 1 */ - BR[3] = GPR[reg]; /* Rd to BR 3 (AP) */ - BR[0] = cfp; /* set current frame pointer into BR[0] */ - BR[2] = cfp; /* set current frame pointer into BR[2] */ - i_flags |= BT; /* we changed the PC, so no PC update */ - } - break; - - case 0xC: /* TPCBR */ /* Transfer program Counter to Base Register */ - if ((MODES & BASEBIT) == 0) /* see if nonbased */ - goto inv; /* invalid instruction in nonbased mode */ - BR[reg] = PSD1 & 0xfffffe; /* save PC from PSD1 into BR */ - break; - - case 0xE: /* RETURN */ /* procedure return for basemode calls */ - if ((MODES & BASEBIT) == 0) /* see if nonbased */ - goto inv; /* invalid instruction in nonbased mode */ - t = BR[0]; /* get frame pointer from BR[0] */ - if ((TRAPME = Mem_read(t+4, &temp))) /* get the word from memory */ - goto newpsd; /* memory read error or map fault */ - /* if Bit0 set, restore all saved regs, else restore only BRs */ - if ((temp & BIT0) == 0) { /* see if GPRs are to be restored */ - /* Bit 0 is not set, so restore all GPRs */ - for (ix=2; ix<8; ix++) - if ((TRAPME = Mem_read(t+ix*4+32, &GPR[ix]))) /* get the word from memory */ - goto newpsd; /* memory read error or map fault */ - } - for (ix=0; ix<8; ix++) - if ((TRAPME = Mem_read(t+ix*4+8, &BR[ix]))) /* get the word from memory */ - goto newpsd; /* memory read error or map fault */ - PSD1 &= ~0x1fffffe; /* leave everything except AEXP bit and PC */ - if ((TRAPME = Mem_read(t, &temp))) /* get the word from memory */ - goto newpsd; /* memory read error or map fault */ - PSD1 |= (temp & 0x01fffffe); /* restore AEXP bit and PC from call frame */ - i_flags |= BT; /* we changed the PC, so no PC update */ - break; - - case 0x1: /* INV */ - case 0x3: /* INV */ - case 0x6: /* INV */ - case 0x7: /* INV */ - case 0x9: /* INV */ - case 0xA: /* INV */ - case 0xB: /* INV */ - case 0xD: /* INV */ - case 0xF: /* INV */ + } else { /* handle nonbase ZBR */ + if (opr & 0xc) { /* any subop not zero is error */ TRAPME = UNDEFINSTR_TRAP; /* Undefined Instruction Trap */ if ((CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9)) TRAPSTATUS |= BIT0; /* set bit 0 of trap status */ goto newpsd; /* handle trap */ + } +zbr: /* handle basemode too */ + /* move the byte field bits 14-15 to bits 27-28 */ + /* or in the bit# from dest reg field bits 6-8 into bit 29-31 */ + bc = (((opr << 3) & 0x18) | reg); /* get # bits to shift right */ + bc = BIT0 >> bc; /* make a bit mask of bit number */ + t = (PSD1 & 0x70000000) >> 1; /* get old CC bits 1-3 into CCs 2-4*/ + PSD1 &= 0x87FFFFFE; /* clear the old CC's */ + if (GPR[sreg] & bc) /* test the bit in src reg */ + t |= CC1BIT; /* set CC1 to the bit value */ + GPR[sreg] &= ~bc; /* reset the bit in src reg */ + PSD1 |= t; /* update the CC's in the PSD */ + } + break; + + case 0x20>>2: /* 0x20 HLF - HLF */ /* ABR (basemode SRAD, SRLD, SLAD, SLLD) */ + if (MODES & BASEBIT) { /* handle basemode SRAD, SRLD, SLAD, SLLD */ + if (reg & 1) { /* see if odd reg specified */ + TRAPME = ADDRSPEC_TRAP; /* bad reg address, error */ + goto newpsd; /* go execute the trap now */ + } + dest = (t_uint64)GPR[reg+1]; /* get low order reg value */ + dest |= (((t_uint64)GPR[reg]) << 32); /* insert upper reg value */ + bc = opr & 0x1f; /* get bit shift count */ + source = dest & DMSIGN; /* 64 bit sign value */ + switch (opr & 0x60) { + case 0x00: /* SRAD instruction */ + for (ix=0; ix>= 1; /* shift bit 0 right one bit */ + dest |= source; /* restore original sign bit */ + } + break; + + case 0x20: /* SRLD */ + dest >>= bc; /* shift right #bits */ + break; + + case 0x40: /* SLAD instruction */ + ovr = 0; /* set ovr off */ + for (ix=0; ix>32) & FMASK);/* save the hi order reg */ + PSD1 &= 0x87FFFFFE; /* clear the old CC's */ + if (ovr) + PSD1 |= BIT1; /* CC1 in PSD */ + /* the arithmetic exception will be handled */ + /* after instruction is completed */ + /* check for arithmetic exception trap enabled */ + if (ovr && (MODES & AEXPBIT)) { + TRAPME = AEXPCEPT_TRAP; /* set the trap type */ + goto newpsd; /* go execute the trap now */ + } + break; + + case 0x60: /* SLLD */ + dest <<= bc; /* shift left #bits */ break; } + GPR[reg+1] = (uint32)(dest & FMASK); /* save the low order reg */ + GPR[reg] = (uint32)((dest>>32) & FMASK);/* save the hi order reg */ break; - case 0x2C>>2: /* 0x2C HLF - HLF */ /* Reg-Reg instructions */ - temp = GPR[reg]; /* reg contents specified by Rd */ - addr = GPR[sreg]; /* reg contents specified by Rs */ - bc = 0; - - switch(opr & 0xF) { - case 0x0: /* TRR */ /* SCC|SD|R1 */ - temp = addr; /* set value to go to GPR[reg] */ - bc = 1; /* set CC's at end */ - break; - - case 0x1: /* TRBR */ /* Transfer GPR to BR */ - if ((MODES & BASEBIT) == 0) /* see if nonbased */ - goto inv; /* invalid instruction in nonbased mode */ - BR[reg] = GPR[sreg]; /* copy GPR to BR */ - break; - - case 0x2: /* TBRR */ /* transfer BR to GPR */ - if ((MODES & BASEBIT) == 0) /* see if nonbased */ - goto inv; /* invalid instruction in nonbased mode */ - temp = BR[sreg]; /* set base reg value */ - bc = 1; /* set CC's at end */ - break; - - case 0x3: /* TRC */ /* Transfer register complement */ - temp = addr ^ FMASK; /* complement Rs */ - bc = 1; /* set CC's at end */ - break; - - case 0x4: /* TRN */ /* Transfer register negative */ - temp = NEGATE32(addr); /* negate Rs value */ - if (temp == addr) /* overflow if nothing changed */ - ovr = 1; /* set overflow flag */ - /* reset ovr if val == 0, not set for DIAGS */ - if ((temp == 0) & ovr) - ovr = 0; - bc = 1; /* set the CC's */ - break; - - case 0x5: /* XCR */ /* exchange registers Rd & Rs */ - GPR[sreg] = temp; /* Rd to Rs */ - set_CCs(temp, ovr); /* set the CC's from original Rd */ - temp = addr; /* save the Rs value to Rd reg */ - break; - - case 0x6: /* INV */ - goto inv; - break; - - case 0x7: /* LMAP */ /* Load map reg - Diags only */ - if ((MODES & PRIVBIT) == 0) { /* must be privileged */ -//sim_debug(DEBUG_EXP, &cpu_dev, "Privledged violation LMAP\n"); - TRAPME = PRIVVIOL_TRAP; /* set the trap to take */ - if ((CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9)) - TRAPSTATUS |= BIT0; /* set bit 0 of trap status */ - else - TRAPSTATUS |= BIT19; /* set bit 19 of trap status */ - goto newpsd; /* handle trap */ - } - /* cpu must be unmapped */ - if (MODES & MAPMODE) { /* must be unmapped cpu */ - TRAPME = MAPFAULT_TRAP; /* Map Fault Trap */ - if ((CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9)) - TRAPSTATUS |= BIT8; /* set bit 8 of trap status */ - else - TRAPSTATUS |= BIT19; /* set bit 19 of trap status */ - goto newpsd; /* handle trap */ - } - { /* load the cpu maps using diag psd */ - uint32 DPSD[2]; /* the PC for the instruction */ - /* get PSD pointed to by real addr in Rd (temp) */ - DPSD[0] = RMW(temp); /* get word one of psd */ - DPSD[1] = RMW(temp+4); /* get word two of psd */ - sim_debug(DEBUG_CMD, &cpu_dev, - "LMAP PSD %08x %08x DPSD %08x %08x modes %08x temp %06x\n", - PSD1, PSD2, DPSD[0], DPSD[1], MODES, temp); - if ((DPSD[1] & MAPBIT) == 0) /* if PSD2 is unmapped, treat as NOP */ - goto skipit; - if (PSD2 & RETMBIT) /* don't load maps if retain bit set */ - goto skipit; - temp2 = MODES; /* save modes bits through load_maps call */ - MODES = DPSD[0] & 0x87000000; /* extract bits 0, 5, 6, 7 from PSD 1 */ - MODES |= MAPMODE; /* set mapped mode flag for load_maps call */ - sim_debug(DEBUG_CMD, &cpu_dev, - "LMAP PSD %08x %08x DPSD %08x %08x modes %08x temp2 %08x\n", - PSD1, PSD2, DPSD[0], DPSD[1], MODES, temp2); - /* we need to load the new maps */ - TRAPME = load_maps(DPSD, 1); /* load maps for new PSD */ - sim_debug(DEBUG_CMD, &cpu_dev, - "LMAP TRAPME %08x MAPC[8-c] %08x %08x %08x %08x %08x %08x\n", - TRAPME, MAPC[7], MAPC[8], MAPC[9], MAPC[10], MAPC[11], MAPC[12]); - MODES = temp2; /* restore modes flags */ - if (TRAPME) { - /* DIAGS wants the cpix for the psd to be the requested one */ - PSD2 = (PSD2 & 0xffffc000) | (DPSD[1] & 0x3ff8); - goto newpsd; /* handle trap */ - } - goto skipit; - break; - } - break; - - case 0x8: /* TRRM */ /* SCC|SD|R1 */ - temp = addr & GPR[4]; /* transfer reg-reg masked */ - bc = 1; /* set CC's at end */ - break; - - /* CPUSTATUS bits */ - /* Bits 0-19 reserved */ - /* Bit 20 =0 Write to writable control store is disabled */ - /* =1 Write to writable control store is enabled */ - /* Bit 21 =0 Enable PROM mode */ - /* =1 Enable Alterable Control Store Mode */ - /* Bit 22 =0 Enable High Speed Floating Point Accelerator */ - /* =1 Disable High Speed Floating Point Accelerator */ - /* Bit 23 =0 Disable privileged mode halt trap */ - /* =1 Enable privileged mode halt trap */ - /* Bit 24 is reserved */ - /* bit 25 =0 Disable software trap handling (enable automatic trap handling) */ - /* =1 Enable software trap handling */ - /* Bits 26-31 reserved */ - case 0x9: /* SETCPU */ - if ((MODES & PRIVBIT) == 0) { /* must be privileged */ -//sim_debug(DEBUG_EXP, &cpu_dev, "Privledged violation SETCPU\n"); - TRAPME = PRIVVIOL_TRAP; /* set the trap to take */ - if ((CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9)) - TRAPSTATUS |= BIT0; /* set bit 0 of trap status */ - else - TRAPSTATUS |= BIT19; /* set bit 19 of trap status */ - goto newpsd; /* handle trap */ - } - temp2 = CPUSTATUS; /* save original */ - /* bits 20-23 and bit 25 can change */ - CPUSTATUS &= 0xfffff0bf; /* zero bits that can change */ - CPUSTATUS |= (temp & 0x0f40); /* or in the new status bits */ - CPUSTATUS |= BIT22; /* HS Floating is set to off */ - /* make sure WCS is off and prom mode set to 0 (on) */ - CPUSTATUS &= ~(BIT20|BIT21); /* make zero */ - sim_debug(DEBUG_CMD, &cpu_dev, - "SETCPU orig %08x user bits %08x New CPUSTATUS %08x SPAD[f5] %08x\n", - temp2, temp, CPUSTATUS, SPAD[0xf9]); - SPAD[0xf9] = CPUSTATUS; /* save the cpu status in SPAD */ -#if 0 -#define DO_DYNAMIC_DEBUG -#ifdef DO_DYNAMIC_DEBUG - if (temp == 0x140) { - cpu_dev.dctrl |= DEBUG_INST; /* start instruction trace */ - } -#endif -#endif - break; - - case 0xA: /* TMAPR */ /* Transfer map to Reg - Diags only */ - if ((MODES & PRIVBIT) == 0) { /* must be privileged */ -//sim_debug(DEBUG_EXP, &cpu_dev, "Privledged violation TMAPR\n"); - TRAPME = PRIVVIOL_TRAP; /* set the trap to take */ - if ((CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9)) - TRAPSTATUS |= BIT0; /* set bit 0 of trap status */ - else - TRAPSTATUS |= BIT19; /* set bit 19 of trap status */ - goto newpsd; /* handle trap */ - } - if (CPU_MODEL <= MODEL_27) { /* 7X & 27 must be unmapped */ - if (MODES & MAPMODE) { /* must be unmapped cpu */ - TRAPME = MAPFAULT_TRAP; /* Map Fault Trap */ - goto newpsd; /* handle trap */ - } - } - /* Rs has map number for even/odd pair loading */ - if (CPU_MODEL < MODEL_27) { - /* 32/77 with 32 map regs */ - addr &= 0x1e; /* make 0-15 */ - temp = MAPC[addr>>1]; /* get even/odd maps */ - } else - if ((CPU_MODEL == MODEL_27) || (CPU_MODEL == MODEL_87)) { - /* 32/27 & 32/87 have 256 maps */ - addr &= 0xfe; /* make 0-255 */ - temp = MAPC[addr>>1]; /* get even/odd maps */ - } else { - /* 32/67, 32/97, V6 & V9 have 2048 maps demand paging */ - addr &= 0x7ff; /* make 0-2047 */ - temp = MAPC[addr>>1]; /* get even/odd maps */ - if ((addr & 1) == 0) /* if even reg, use left hw */ - temp >>= 16; /* move over reg value */ - temp &= 0xffff; /* just 16 bits */ - if (TLB[addr] & 0x04000000) /* see if HIT bit set */ - temp |= 0x80000000; /* show hit BIT is set */ - temp |= ((TLB[addr] & 0xf8000000) >> 16); /* add in protect bits */ - if ((addr < 0x26) || (addr > 0x7f8)) - sim_debug(DEBUG_CMD, &cpu_dev, - "TMAPR #%4x val %08x TLB %08x RMR %04x MAPC %08x\n", - addr, temp, TLB[addr], RMR(addr<<1), MAPC[addr/2]); - } - GPR[reg] = temp; /* save the temp value to Rd reg */ - goto skipit; - break; - - case 0xB: /* TRCM */ /* Transfer register complemented masked */ - temp = (addr ^ FMASK) & GPR[4]; /* compliment & mask */ - bc = 1; /* set the CC's */ - break; - - case 0xC: /* TRNM */ /* Transfer register negative masked */ - temp = NEGATE32(addr); /* complement GPR[reg] */ - if (temp == addr) /* check for overflow */ - ovr = 1; /* overflow */ - /* reset ovr if val == 0, not set for DIAGS */ - if ((temp == 0) & ovr) - ovr = 0; - temp &= GPR[4]; /* and with negative reg */ - bc = 1; /* set the CC's */ - break; - - case 0xD: /* XCRM */ /* Exchange registers masked */ - addr &= GPR[4]; /* and Rs with mask reg */ - temp &= GPR[4]; /* and Rd with mask reg */ - GPR[sreg] = temp; /* Rs to get Rd masked value */ - set_CCs(temp, ovr); /* set the CC's from original Rd */ - temp = addr; /* save the Rs value to Rd reg */ - break; - - case 0xE: /* TRSC */ /* transfer reg to SPAD */ - if ((MODES & PRIVBIT) == 0) { /* must be privileged */ -//sim_debug(DEBUG_EXP, &cpu_dev, "Privledged violation TRSC\n"); - TRAPME = PRIVVIOL_TRAP; /* set the trap to take */ - if ((CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9)) - TRAPSTATUS |= BIT0; /* set bit 0 of trap status */ - else - TRAPSTATUS |= BIT19; /* set bit 19 of trap status */ - goto newpsd; /* handle trap */ - } - t = (GPR[reg] >> 16) & 0xff; /* get SPAD address from Rd (6-8) */ - temp2 = SPAD[t]; /* get old SPAD data */ - SPAD[t] = GPR[sreg]; /* store Rs into SPAD */ - break; - - case 0xF: /* TSCR */ /* Transfer scratchpad to register */ - if ((MODES & PRIVBIT) == 0) { /* must be privileged */ -//sim_debug(DEBUG_EXP, &cpu_dev, "Privledged violation TSCR\n"); - TRAPME = PRIVVIOL_TRAP; /* set the trap to take */ - if ((CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9)) - TRAPSTATUS |= BIT0; /* set bit 0 of trap status */ - else - TRAPSTATUS |= BIT19; /* set bit 19 of trap status */ - goto newpsd; /* handle trap */ - } - t = (GPR[sreg] >> 16) & 0xff; /* get SPAD address from Rs (9-11) */ - temp = SPAD[t]; /* get SPAD data into Rd (6-8) */ - break; + } else { /* handle nonbase mode ABR */ + if (opr & 0xc) { /* any subop not zero is error */ + TRAPME = UNDEFINSTR_TRAP; /* Undefined Instruction Trap */ + if ((CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9)) + TRAPSTATUS |= BIT0; /* set bit 0 of trap status */ + goto newpsd; /* handle trap */ } - GPR[reg] = temp; /* save the temp value to Rd reg */ - if (bc) /* set cc's if bc set */ - set_CCs(temp, ovr); /* set the CC's */ +abr: /* basemode ABR too */ + /* move the byte field bits 14-15 to bits 27-28 */ + /* or in the bit# from dest reg field bits 6-8 into bit 29-31 */ + bc = (((opr << 3) & 0x18) | reg); /* get # bits to shift right */ + bc = BIT0 >> bc; /* make a bit mask of bit number */ + temp = GPR[sreg]; /* get reg value to add bit to */ + t = (temp & FSIGN) != 0; /* set flag for sign bit not set in temp value */ + t |= ((bc & FSIGN) != 0) ? 2 : 0; /* ditto for the bit value */ + temp += bc; /* add the bit value to the reg */ + /* if both signs are neg and result sign is positive, overflow */ + /* if both signs are pos and result sign is negative, overflow */ + if ((t == 3 && (temp & FSIGN) == 0) || + (t == 0 && (temp & FSIGN) != 0)) { + ovr = 1; /* we have an overflow */ + } + GPR[sreg] = temp; /* save the new value */ + set_CCs(temp, ovr); /* set the CC's, CC1 = ovr */ /* the arithmetic exception will be handled */ /* after instruction is completed */ /* check for arithmetic exception trap enabled */ @@ -3745,1307 +3284,2190 @@ tbr: /* handle basemode TBR too * TRAPME = AEXPCEPT_TRAP; /* set the trap type */ goto newpsd; /* handle trap */ } -skipit: - /* for retain, leave PSD2 alone */ + } + break; + + case 0x24>>2: /* 0x24 HLF - HLF */ /* TBR (basemode SRC) */ + if (MODES & BASEBIT) { /* handle SRC basemode */ + bc = opr & 0x1f; /* get bit shift count */ + temp = GPR[reg]; /* get reg value to shift */ + if ((opr & 0x60) == 0x40) { /* SLC instruction */ + for (ix=0; ix>= 1; /* shift the bit out */ + if (t) + temp |= BIT0; /* put in new sign bit */ + } + } + GPR[reg] = temp; /* shift result */ + } else { /* handle TBR non basemode */ + if (opr & 0xc) { /* any subop not zero is error */ + TRAPME = UNDEFINSTR_TRAP; /* Undefined Instruction Trap */ + if ((CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9)) + TRAPSTATUS |= BIT0; /* set bit 0 of trap status */ + goto newpsd; /* handle trap */ + } +tbr: /* handle basemode TBR too */ + /* move the byte field bits 14-15 to bits 27-28 */ + /* or in the bit# from dest reg field bits 6-8 into bit 29-31 */ + bc = (((opr << 3) & 0x18) | reg); /* get # bits to shift right */ + bc = BIT0 >> bc; /* make a bit mask of bit number */ + t = (PSD1 & 0x70000000) >> 1; /* get old CC bits 1-3 into CCs 2-4*/ + PSD1 &= 0x87FFFFFE; /* clear the old CC's */ + if (GPR[sreg] & bc) /* test the bit in src reg */ + t |= CC1BIT; /* set CC1 to the bit value */ + PSD1 |= t; /* update the CC's in the PSD */ + } + break; + + case 0x28>>2: /* 0x28 HLF - HLF */ /* Misc OP REG instructions */ + switch(opr & 0xF) { + case 0x0: /* TRSW */ + if (MODES & BASEBIT) + temp = 0x78FFFFFE; /* bits 1-4 and 24 bit addr for based mode */ + else + temp = 0x7807FFFE; /* bits 1-4 and 19 bit addr for non based mode */ + addr = GPR[reg]; /* get reg value */ + /* we are returning to the addr in reg, set CC's from reg */ + /* update the PSD with new address from reg */ + PSD1 &= ~temp; /* clean the bits to be changed */ + PSD1 |= (addr & temp); /* insert the CC's and address */ + sim_debug(DEBUG_DETAIL, &cpu_dev, + "TRSW REG %01x PSD %08x %08x modes %08x temp %06x\n", + reg, PSD1, PSD2, MODES, temp); + i_flags |= BT; /* we branched, so no PC update */ break; - case 0x30>>2: /* 0x30 */ /* CALM */ - /* Process CALM for 32/27 when in left hw, else invalid */ - if ((CPU_MODEL <= MODEL_87) && (CPU_MODEL != MODEL_67)) { - uint32 oldstatus = CPUSTATUS; /* keep for retain blocking state */ - /* DIAG error for 32/27 or 32/87 only */ - if ((PSD1 & 2) != 0) /* is it lf hw instruction */ - goto inv; /* invalid instr if in rt hw */ - addr = SPAD[0xf0]; /* get trap table memory address from SPAD (def 80) */ - if (addr == 0 || addr == 0xffffffff) { /* see if secondary vector table set up */ - TRAPME = ADDRSPEC_TRAP; /* Not setup, error */ - goto newpsd; /* program error */ + case 0x2: /* XCBR */ /* Exchange base registers */ + if ((MODES & BASEBIT) == 0) /* see if nonbased */ + goto inv; /* invalid instruction in nonbased mode */ + temp = BR[reg]; /* get dest reg value */ + BR[reg] = BR[sreg]; /* put source reg value int dest reg */ + BR[sreg] = temp; /* put dest reg value into src reg */ + break; + + case 0x4: /* TCCR */ /* Transfer condition codes to GPR bits 28-31 */ + if ((MODES & BASEBIT) == 0) /* see if nonbased */ + goto inv; /* invalid instruction in nonbased mode */ + temp = CC >> 27; /* right justify CC's in reg */ + GPR[reg] = temp; /* put dest reg value into src reg */ + break; + + case 0x5: /* TRCC */ /* Transfer GPR bits 28-31 to condition codes */ + if ((MODES & BASEBIT) == 0) /* see if nonbased */ + goto inv; /* invalid instruction in nonbased mode */ + PSD1 = ((PSD1 & 0x87fffffe)|((GPR[reg] & 0xf) << 27)); /* insert CCs from reg */ + break; + + case 0x8: /* BSUB */ /* Procedure call */ + if ((MODES & BASEBIT) == 0) /* see if nonbased */ + goto inv; /* invalid instruction in nonbased mode */ + + /* if Rd field is 0 (reg is b6-b8), this is a BSUB instruction */ + /* otherwise it is a CALL instruction (Rd != 0) */ + if (reg == 0) { + /* BSUB instruction */ + uint32 cfp = BR[2]; /* get dword bounded frame pointer from BR2 */ + if ((BR[2] & 0x7) != 0) { + /* Fault, must be dw bounded address */ + TRAPME = ADDRSPEC_TRAP; /* bad address, error */ + goto newpsd; /* go execute the trap now */ } - addr = addr + (0x0A << 2); /* addr has mem addr of CALM trap vector (def A8) */ - t = M[addr >> 2]; /* get the ICB address from memory */ - if (t == 0 || t == 0xffffffff) { /* see if ICB set up */ - TRAPME = ADDRSPEC_TRAP; /* Not setup, error */ - goto newpsd; /* program error */ + cfp = BR[2] & 0x00fffff8; /* clean the cfp address to 24 bit dw */ + + M[cfp>>2] = (PSD1 + 2) & 0x01fffffe; /* save AEXP bit and PC into frame */ + M[(cfp>>2)+1] = 0x80000000; /* show frame created by BSUB instr */ + BR[1] = BR[sreg] & MASK24; /* Rs reg to BR 1 */ + PSD1 = (PSD1 & 0xff000000) | (BR[1] & MASK24); /* New PSD address */ + BR[3] = GPR[0]; /* GPR 0 to BR 3 (AP) */ + BR[0] = cfp; /* set frame pointer from BR 2 into BR 0 */ + i_flags |= BT; /* we changed the PC, so no PC update */ + } else + { + /* CALL instruction */ + /* get frame pointer from BR2-16 words & make it a dword addr */ + uint32 cfp = ((BR[2]-0x40) & 0x00fffff8); + + /* if cfp and cfp+15w are in different maps, then addr exception error */ + if ((cfp & 0xffe000) != ((cfp+0x3f) & 0xffe000)) { + TRAPME = ADDRSPEC_TRAP; /* bad reg address, error */ + goto newpsd; /* go execute the trap now */ } - bc = PSD2 & 0x3ff8; /* get copy of cpix */ - /* this will skip over rt hw instruction if any */ - PSD1 = (PSD1 + 4) | (((PSD1 & 2) >> 1) & 1); /* bump pc by 1 wd */ - M[t>>2] = PSD1 & 0xfffffffe; /* store PSD 1 + 1HW to point to next instruction */ - M[(t>>2)+1] = PSD2; /* store PSD 2 */ - PSD1 = M[(t>>2)+2]; /* get new PSD 1 */ - PSD2 = (M[(t>>2)+3] & ~0x3fff) | bc; /* get new PSD 2 w/old cpix */ - M[(t>>2)+4] = opr & 0x03FF; /* store calm number in bits 6-15 */ - /* set the mode bits and CCs from the new PSD */ - CC = PSD1 & 0x78000000; /* extract bits 1-4 from PSD1 */ - MODES = PSD1 & 0x87000000; /* extract bits 0, 5, 6, 7 from PSD 1 */ - CPUSTATUS &= ~0x87000000; /* reset bits in CPUSTATUS */ - CPUSTATUS |= MODES; /* now insert into CPUSTATUS */ + temp = (PSD1+2) & 0x01fffffe; /* save AEXP bit and PC from PSD1 in to frame */ + if ((TRAPME = Mem_write(cfp, &temp))) { /* Save the PSD into memory */ + goto newpsd; /* memory write error or map fault */ + } - /* set new map mode and interrupt blocking state in CPUSTATUS */ - if (PSD2 & MAPBIT) { - CPUSTATUS |= BIT8; /* set bit 8 of cpu status */ - MODES |= MAPMODE; /* set mapped mode */ - } else - CPUSTATUS &= ~BIT8; /* reset bit 8 of cpu status */ + temp = 0x00000000; /* show frame created by CALL instr */ + if ((TRAPME = Mem_write(cfp+4, &temp))) { /* Save zero into memory */ + goto newpsd; /* memory write error or map fault */ + } - /* set interrupt blocking state */ - if ((PSD2 & RETBBIT) == 0) { /* is it retain blocking state */ - if (PSD2 & SETBBIT) { /* no, is it set blocking state */ - CPUSTATUS |= BIT24; /* yes, set blk state in cpu status bit 24 */ - MODES |= BLKMODE; /* set blocked mode */ - } else { - CPUSTATUS &= ~BIT24; /* no, reset blk state in cpu status bit 24 */ - MODES &= ~BLKMODE; /* reset blocked mode */ - irq_pend = 1; /* start scanning interrupts again */ -#ifdef LEAVE_ACTIVE - if (irq_auto) { -/*AIR*/ INTS[irq_auto] &= ~INTS_ACT; /* deactivate specified int level */ -/*AIR*/ SPAD[irq_auto+0x80] &= ~SINT_ACT; /* deactivate in SPAD too */ - sim_debug(DEBUG_IRQ, &cpu_dev, - "<|>IntX deactivate level %02x at CALM PSD1 %08x\n", - irq_auto, PSD1); -/*AIR*/ irq_auto = 0; /* show done processing in blocked mode */ -/*103020*/ skipinstr = 1; /* skip interrupt test */ - } -#endif - } - } else { - /* handle retain blocking state */ - PSD2 &= ~RETMBIT; /* turn off retain bit in PSD2 */ - /* set new blocking state in PSD2 */ - PSD2 &= ~(SETBBIT|RETBBIT); /* clear bit 48 & 49 to be unblocked */ - MODES &= ~(BLKMODE|RETMODE);/* reset blocked & retain mode bits */ - if (oldstatus & BIT24) { /* see if old mode is blocked */ - PSD2 |= SETBBIT; /* set to blocked state */ - MODES |= BLKMODE; /* set blocked mode */ + /* Save BR 0-7 to stack */ + for (ix=0; ix<8; ix++) { + if ((TRAPME = Mem_write(cfp+(4*ix)+8, &BR[ix]))) { /* Save into memory */ + goto newpsd; /* memory write error or map fault */ } } - SPAD[0xf5] = PSD2; /* save the current PSD2 */ - SPAD[0xf9] = CPUSTATUS; /* save the cpu status in SPAD */ - TRAPME = 0; /* not to be processed as trap */ - goto newpsd; /* new psd loaded */ + /* save GPR 2-8 to stack */ + for (ix=2; ix<8; ix++) { + if ((TRAPME = Mem_write(cfp+(4*ix)+32, &GPR[ix]))) { /* Save into memory */ + goto newpsd; /* memory write error or map fault */ + } + } + + /* keep bits 0-7 from old PSD */ + PSD1 = (PSD1 & 0xff000000) | ((BR[sreg]) & MASK24); /* New PSD address */ + BR[1] = BR[sreg]; /* Rs reg to BR 1 */ + BR[3] = GPR[reg]; /* Rd to BR 3 (AP) */ + BR[0] = cfp; /* set current frame pointer into BR[0] */ + BR[2] = cfp; /* set current frame pointer into BR[2] */ + i_flags |= BT; /* we changed the PC, so no PC update */ + } + break; + + case 0xC: /* TPCBR */ /* Transfer program Counter to Base Register */ + if ((MODES & BASEBIT) == 0) /* see if nonbased */ + goto inv; /* invalid instruction in nonbased mode */ + BR[reg] = PSD1 & 0xfffffe; /* save PC from PSD1 into BR */ + break; + + case 0xE: /* RETURN */ /* procedure return for basemode calls */ + if ((MODES & BASEBIT) == 0) /* see if nonbased */ + goto inv; /* invalid instruction in nonbased mode */ + t = BR[0]; /* get frame pointer from BR[0] */ + if ((TRAPME = Mem_read(t+4, &temp))) /* get the word from memory */ + goto newpsd; /* memory read error or map fault */ + /* if Bit0 set, restore all saved regs, else restore only BRs */ + if ((temp & BIT0) == 0) { /* see if GPRs are to be restored */ + /* Bit 0 is not set, so restore all GPRs */ + for (ix=2; ix<8; ix++) + if ((TRAPME = Mem_read(t+ix*4+32, &GPR[ix]))) /* get the word from memory */ + goto newpsd; /* memory read error or map fault */ + } + for (ix=0; ix<8; ix++) { + if ((TRAPME = Mem_read(t+ix*4+8, &BR[ix]))) /* get the word from memory */ + goto newpsd; /* memory read error or map fault */ + } + PSD1 &= ~0x1fffffe; /* leave everything except AEXP bit and PC */ + if ((TRAPME = Mem_read(t, &temp))) /* get the word from memory */ + goto newpsd; /* memory read error or map fault */ + PSD1 |= (temp & 0x01fffffe); /* restore AEXP bit and PC from call frame */ + i_flags |= BT; /* we changed the PC, so no PC update */ + break; + + case 0x1: /* INV */ + case 0x3: /* INV */ + case 0x6: /* INV */ + case 0x7: /* INV */ + case 0x9: /* INV */ + case 0xA: /* INV */ + case 0xB: /* INV */ + case 0xD: /* INV */ + case 0xF: /* INV */ + TRAPME = UNDEFINSTR_TRAP; /* Undefined Instruction Trap */ + if ((CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9)) + TRAPSTATUS |= BIT0; /* set bit 0 of trap status */ + goto newpsd; /* handle trap */ + break; + } + break; + + case 0x2C>>2: /* 0x2C HLF - HLF */ /* Reg-Reg instructions */ + temp = GPR[reg]; /* reg contents specified by Rd */ + addr = GPR[sreg]; /* reg contents specified by Rs */ + bc = 0; + + switch(opr & 0xF) { + case 0x0: /* TRR */ /* SCC|SD|R1 */ + temp = addr; /* set value to go to GPR[reg] */ + bc = 1; /* set CC's at end */ + break; + + case 0x1: /* TRBR */ /* Transfer GPR to BR */ + if ((MODES & BASEBIT) == 0) /* see if nonbased */ + goto inv; /* invalid instruction in nonbased mode */ + BR[reg] = GPR[sreg]; /* copy GPR to BR */ + break; + + case 0x2: /* TBRR */ /* transfer BR to GPR */ + if ((MODES & BASEBIT) == 0) /* see if nonbased */ + goto inv; /* invalid instruction in nonbased mode */ + temp = BR[sreg]; /* set base reg value */ + bc = 1; /* set CC's at end */ + break; + + case 0x3: /* TRC */ /* Transfer register complement */ + temp = addr ^ FMASK; /* complement Rs */ + bc = 1; /* set CC's at end */ + break; + + case 0x4: /* TRN */ /* Transfer register negative */ + temp = NEGATE32(addr); /* negate Rs value */ + if (temp == addr) /* overflow if nothing changed */ + ovr = 1; /* set overflow flag */ + /* reset ovr if val == 0, not set for DIAGS */ + if ((temp == 0) & ovr) + ovr = 0; + bc = 1; /* set the CC's */ + break; + + case 0x5: /* XCR */ /* exchange registers Rd & Rs */ + GPR[sreg] = temp; /* Rd to Rs */ + set_CCs(temp, ovr); /* set the CC's from original Rd */ + temp = addr; /* save the Rs value to Rd reg */ + break; + + case 0x6: /* INV */ + goto inv; + break; + + case 0x7: /* LMAP */ /* Load map reg - Diags only */ + if ((MODES & PRIVBIT) == 0) { /* must be privileged */ + TRAPME = PRIVVIOL_TRAP; /* set the trap to take */ + if ((CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9)) + TRAPSTATUS |= BIT0; /* set bit 0 of trap status */ + else + TRAPSTATUS |= BIT19; /* set bit 19 of trap status */ + goto newpsd; /* handle trap */ + } + /* cpu must be unmapped */ + if (MODES & MAPMODE) { /* must be unmapped cpu */ + TRAPME = MAPFAULT_TRAP; /* Map Fault Trap */ + if ((CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9)) + TRAPSTATUS |= BIT8; /* set bit 8 of trap status */ + else + TRAPSTATUS |= BIT19; /* set bit 19 of trap status */ + goto newpsd; /* handle trap */ + } + { /* load the cpu maps using diag psd */ + uint32 DPSD[2]; /* the PC for the instruction */ + /* get PSD pointed to by real addr in Rd (temp) */ + DPSD[0] = RMW(temp); /* get word one of psd */ + DPSD[1] = RMW(temp+4); /* get word two of psd */ + sim_debug(DEBUG_CMD, &cpu_dev, + "LMAP PSD %08x %08x DPSD %08x %08x modes %08x temp %06x\n", + PSD1, PSD2, DPSD[0], DPSD[1], MODES, temp); + if ((DPSD[1] & MAPBIT) == 0) /* if PSD2 is unmapped, treat as NOP */ + goto skipit; + if (PSD2 & RETMBIT) /* don't load maps if retain bit set */ + goto skipit; + temp2 = MODES; /* save modes bits through load_maps call */ + MODES = DPSD[0] & 0x87000000; /* extract bits 0, 5, 6, 7 from PSD 1 */ + MODES |= MAPMODE; /* set mapped mode flag for load_maps call */ + sim_debug(DEBUG_CMD, &cpu_dev, + "LMAP PSD %08x %08x DPSD %08x %08x modes %08x temp2 %08x\n", + PSD1, PSD2, DPSD[0], DPSD[1], MODES, temp2); + /* we need to load the new maps */ + TRAPME = load_maps(DPSD, 1); /* load maps for new PSD */ + sim_debug(DEBUG_CMD, &cpu_dev, + "LMAP TRAPME %08x MAPC[8-c] %08x %08x %08x %08x %08x %08x\n", + TRAPME, MAPC[7], MAPC[8], MAPC[9], MAPC[10], MAPC[11], MAPC[12]); + MODES = temp2; /* restore modes flags */ + if (TRAPME) { + /* DIAGS wants the cpix for the psd to be the requested one */ + PSD2 = (PSD2 & 0xffffc000) | (DPSD[1] & 0x3ff8); + goto newpsd; /* handle trap */ + } + goto skipit; + break; + } + break; + + case 0x8: /* TRRM */ /* SCC|SD|R1 */ + temp = addr & GPR[4]; /* transfer reg-reg masked */ + bc = 1; /* set CC's at end */ + break; + + /* CPUSTATUS bits */ + /* Bits 0-19 reserved */ + /* Bit 20 =0 Write to writable control store is disabled */ + /* =1 Write to writable control store is enabled */ + /* Bit 21 =0 Enable PROM mode */ + /* =1 Enable Alterable Control Store Mode */ + /* Bit 22 =0 Enable High Speed Floating Point Accelerator */ + /* =1 Disable High Speed Floating Point Accelerator */ + /* Bit 23 =0 Disable privileged mode halt trap */ + /* =1 Enable privileged mode halt trap */ + /* Bit 24 is reserved */ + /* bit 25 =0 Disable software trap handling (enable automatic trap handling) */ + /* =1 Enable software trap handling */ + /* Bits 26-31 reserved */ + case 0x9: /* SETCPU */ + if ((MODES & PRIVBIT) == 0) { /* must be privileged */ + TRAPME = PRIVVIOL_TRAP; /* set the trap to take */ + if ((CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9)) + TRAPSTATUS |= BIT0; /* set bit 0 of trap status */ + else + TRAPSTATUS |= BIT19; /* set bit 19 of trap status */ + goto newpsd; /* handle trap */ + } + temp2 = CPUSTATUS; /* save original */ + /* bits 20-23 and bit 25 can change */ + CPUSTATUS &= 0xfffff0bf; /* zero bits that can change */ + CPUSTATUS |= (temp & 0x0f40); /* or in the new status bits */ + CPUSTATUS |= BIT22; /* HS Floating is set to off */ + /* make sure WCS is off and prom mode set to 0 (on) */ + CPUSTATUS &= ~(BIT20|BIT21); /* make zero */ + sim_debug(DEBUG_CMD, &cpu_dev, + "SETCPU orig %08x user bits %08x New CPUSTATUS %08x SPAD[f5] %08x\n", + temp2, temp, CPUSTATUS, SPAD[0xf9]); + SPAD[0xf9] = CPUSTATUS; /* save the cpu status in SPAD */ + break; + + case 0xA: /* TMAPR */ /* Transfer map to Reg - Diags only */ + if ((MODES & PRIVBIT) == 0) { /* must be privileged */ + TRAPME = PRIVVIOL_TRAP; /* set the trap to take */ + if ((CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9)) + TRAPSTATUS |= BIT0; /* set bit 0 of trap status */ + else + TRAPSTATUS |= BIT19; /* set bit 19 of trap status */ + goto newpsd; /* handle trap */ + } + if (CPU_MODEL <= MODEL_27) { /* 7X & 27 must be unmapped */ + if (MODES & MAPMODE) { /* must be unmapped cpu */ + TRAPME = MAPFAULT_TRAP; /* Map Fault Trap */ + goto newpsd; /* handle trap */ + } + } + /* Rs has map number for even/odd pair loading */ + if (CPU_MODEL < MODEL_27) { + /* 32/77 with 32 map regs */ + addr &= 0x1e; /* make 0-15 */ + temp = MAPC[addr>>1]; /* get even/odd maps */ + } else + if ((CPU_MODEL == MODEL_27) || (CPU_MODEL == MODEL_87)) { + /* 32/27 & 32/87 have 256 maps */ + addr &= 0xfe; /* make 0-255 */ + temp = MAPC[addr>>1]; /* get even/odd maps */ } else { -// fprintf(stderr, "got CALM trap\r\n"); - goto inv; /* invalid instr */ + /* 32/67, 32/97, V6 & V9 have 2048 maps demand paging */ + addr &= 0x7ff; /* make 0-2047 */ + temp = MAPC[addr>>1]; /* get even/odd maps */ + if ((addr & 1) == 0) /* if even reg, use left hw */ + temp >>= 16; /* move over reg value */ + temp &= 0xffff; /* just 16 bits */ + if (TLB[addr] & 0x04000000) /* see if HIT bit set */ + temp |= 0x80000000; /* show hit BIT is set */ + temp |= ((TLB[addr] & 0xf8000000) >> 16); /* add in protect bits */ + if ((addr < 0x26) || (addr > 0x7f8)) + sim_debug(DEBUG_CMD, &cpu_dev, + "TMAPR #%4x val %08x TLB %08x RMR %04x MAPC %08x\n", + addr, temp, TLB[addr], RMR(addr<<1), MAPC[addr/2]); } + GPR[reg] = temp; /* save the temp value to Rd reg */ + goto skipit; break; - case 0x34>>2: /* 0x34 SD|ADR - inv */ /* LA non-basemode */ - if (MODES & BASEBIT) /* see if based */ - goto inv; /* invalid instruction in based mode */ - if (MODES & EXTDBIT) { /* see if extended mode */ - dest = (t_uint64)(addr&MASK24); /* just pure 24 bit address */ - } else { /* use bits 13-31 */ - dest = (t_uint64)((addr&0x7ffff) | ((FC & 4) << 17)); /* F bit to bit 12 */ - } + case 0xB: /* TRCM */ /* Transfer register complemented masked */ + temp = (addr ^ FMASK) & GPR[4]; /* compliment & mask */ + bc = 1; /* set the CC's */ break; - case 0x38>>2: /* 0x38 HLF - HLF */ /* REG - REG floating point */ - switch(opr & 0xF) { - case 0x0: /* ADR */ - temp = GPR[reg]; /* reg contents specified by Rd */ - addr = GPR[sreg]; /* reg contents specified by Rs */ - t = (temp & FSIGN) != 0; /* set flag for sign bit not set in temp value */ - t |= ((addr & FSIGN) != 0) ? 2 : 0; /* ditto for the reg value */ - temp = temp + addr; /* add the values */ - /* if both signs are neg and result sign is positive, overflow */ - /* if both signs are pos and result sign is negative, overflow */ - if ((t == 3 && (temp & FSIGN) == 0) || - (t == 0 && (temp & FSIGN) != 0)) { - ovr = 1; /* we have an overflow */ - } - i_flags |= SF; /* special processing */ - break; - - case 0x1: /* ADRFW */ - case 0x3: /* SURFW */ - /* TODO not on 32/27 */ - temp = GPR[reg]; /* reg contents specified by Rd */ - addr = GPR[sreg]; /* reg contents specified by Rs */ - /* temp has Rd (GPR[reg]), addr has Rs (GPR[sreg]) */ - if ((opr & 0xF) == 0x3) { - addr = NEGATE32(addr); /* subtract, so negate source */ - } - temp2 = s_adfw(temp, addr, &CC); /* do ADFW */ - sim_debug(DEBUG_DETAIL, &cpu_dev, - "%s GPR[%d] %08x addr %08x result %08x CC %08x\n", - (opr&0xf)==3 ? "SURFW":"ADRFW", - reg, GPR[reg], GPR[sreg], temp2, CC); - PSD1 &= 0x87FFFFFE; /* clear the old CC's */ - PSD1 |= (CC & 0x78000000); /* update the CC's in the PSD */ - if (CC & CC1BIT) { /* check for arithmetic exception */ - ovr = 1; /* exception */ - /* leave Rd & Rs unchanged if AEXPBIT is set */ - if (MODES & AEXPBIT) { - TRAPME = AEXPCEPT_TRAP; /* trap the system now */ - goto newpsd; /* process the trap */ - } - } - /* AEXPBIT not set, so save the fixed return value */ - /* return result to destination reg */ - GPR[reg] = temp2; /* dest - reg contents specified by Rd */ - break; - - case 0x2: /* MPRBR */ - /* TODO not on 32/27 */ - if ((MODES & BASEBIT) == 0) /* see if nonbased */ - goto inv; /* invalid instruction in nonbased mode */ - if (reg & 1) { - /* Spec fault if not even reg */ - TRAPME = ADDRSPEC_TRAP; /* bad reg address, error */ - goto newpsd; /* go execute the trap now */ - } - temp = GPR[reg+1]; /* get multiplicand */ - addr = GPR[sreg]; /* multiplier */ - - /* change value into a 64 bit value */ - dest = ((t_uint64)(addr & FMASK)) | ((addr & FSIGN) ? D32LMASK : 0); - source = ((t_uint64)(temp & FMASK)) | ((temp & FSIGN) ? D32LMASK : 0); - dest = dest * source; /* do the multiply */ - i_flags |= (SD|SCC); /* save dest reg and set CC's */ - dbl = 1; /* double reg save */ - break; - - case 0x4: /* DVRFW */ - /* TODO not on 32/27 */ - temp = GPR[reg]; /* reg contents specified by Rd */ - addr = GPR[sreg]; /* reg contents specified by Rs */ - /* temp has Rd (GPR[reg]), addr has Rs (GPR[sreg]) */ - temp2 = (uint32)s_dvfw(temp, addr, &CC); /* divide reg by sreg */ - sim_debug(DEBUG_DETAIL, &cpu_dev, - "DVRFW GPR[%d] %08x src %08x result %08x\n", - reg, GPR[reg], addr, temp2); - PSD1 &= 0x87FFFFFE; /* clear the old CC's */ - PSD1 |= (CC & 0x78000000); /* update the CC's in the PSD */ - if (CC & CC1BIT) { /* check for arithmetic exception */ - ovr = 1; /* exception */ - /* leave Rd & Rs unchanged if AEXPBIT is set */ - if (MODES & AEXPBIT) { - TRAPME = AEXPCEPT_TRAP; /* trap the system now */ - goto newpsd; /* process the trap */ - } - } - /* AEXPBIT not set, so save the fixed return value */ - /* return result to destination reg */ - GPR[reg] = temp2; /* dest - reg contents specified by Rd */ - break; - - case 0x5: /* FIXW */ - /* TODO not on 32/27 */ - /* convert from 32 bit float to 32 bit fixed */ - addr = GPR[sreg]; /* reg contents specified by Rs */ - temp2 = s_fixw(addr, &CC); /* do conversion */ - sim_debug(DEBUG_DETAIL, &cpu_dev, - "FIXW GPR[%d] %08x result %08x\n", - sreg, GPR[sreg], temp2); - PSD1 &= 0x87FFFFFE; /* clear the old CC's */ - PSD1 |= (CC & 0x78000000); /* update the CC's in the PSD */ - if (CC & CC1BIT) { /* check for arithmetic exception */ - ovr = 1; /* exception */ - /* leave Rd & Rs unchanged if AEXPBIT is set */ - if (MODES & AEXPBIT) { - TRAPME = AEXPCEPT_TRAP; /* trap the system now */ - goto newpsd; /* process the trap */ - } - } - /* AEXPBIT not set, so save the fixed return value */ - /* return result to destination reg */ - GPR[reg] = temp2; /* dest - reg contents specified by Rd */ - break; /* go set CC's */ - - case 0x6: /* MPRFW */ - /* TODO not on 32/27 */ - temp = GPR[reg]; /* reg contents specified by Rd */ - addr = GPR[sreg]; /* reg contents specified by Rs */ - /* temp has Rd (GPR[reg]), addr has Rs (GPR[sreg]) */ - temp2 = s_mpfw(temp, addr, &CC); /* mult reg by sreg */ - sim_debug(DEBUG_DETAIL, &cpu_dev, - "MPRFW GPR[%d] %08x src %08x result %08x\n", - reg, GPR[reg], addr, temp2); - PSD1 &= 0x87FFFFFE; /* clear the old CC's */ - PSD1 |= (CC & 0x78000000); /* update the CC's in the PSD */ - if (CC & CC1BIT) { /* check for arithmetic exception */ - ovr = 1; /* exception */ - /* leave Rd & Rs unchanged if AEXPBIT is set */ - if (MODES & AEXPBIT) { - TRAPME = AEXPCEPT_TRAP; /* trap the system now */ - goto newpsd; /* process the trap */ - } - } - /* AEXPBIT not set, so save the fixed return value */ - /* return result to destination reg */ - GPR[reg] = temp2; /* dest - reg contents specified by Rd */ - break; - - case 0x7: /* FLTW */ - /* TODO not on 32/27 */ - /* convert from 32 bit integer to 32 bit float */ - addr = GPR[sreg]; /* reg contents specified by Rs */ - GPR[reg] = s_fltw(addr, &CC); /* do conversion & set CC's */ - sim_debug(DEBUG_DETAIL, &cpu_dev, - "FLTW GPR[%d] %08x result %08x\n", - sreg, GPR[sreg], GPR[reg]); - PSD1 &= 0x87FFFFFE; /* clear the old CC's */ - PSD1 |= (CC & 0x78000000); /* update the CC's in the PSD */ - break; - - case 0x8: /* ADRM */ - temp = GPR[reg]; /* reg contents specified by Rd */ - addr = GPR[sreg]; /* reg contents specified by Rs */ - t = (temp & FSIGN) != 0; /* set flag for sign bit not set in temp value */ - t |= ((addr & FSIGN) != 0) ? 2 : 0; /* ditto for the reg value */ - temp = temp + addr; /* add the values */ - /* if both signs are neg and result sign is positive, overflow */ - /* if both signs are pos and result sign is negative, overflow */ - if ((t == 3 && (temp & FSIGN) == 0) || - (t == 0 && (temp & FSIGN) != 0)) - ovr = 1; /* we have an overflow */ - temp &= GPR[4]; /* mask the destination reg */ - i_flags |= SF; /* special processing */ - break; - - case 0x9: /* ADRFD */ - case 0xB: /* SURFD */ - /* TODO not on 32/27 */ - if ((reg & 1) || (sreg & 1)) { /* see if any odd reg specified */ - TRAPME = ADDRSPEC_TRAP; /* bad reg address, error */ - goto newpsd; /* go execute the trap now */ - } - td = (((t_uint64)GPR[reg]) << 32); /* get upper reg value */ - td |= (t_uint64)GPR[reg+1]; /* insert low order reg value */ - source = (((t_uint64)GPR[sreg]) << 32); /* get upper reg value */ - source |= (t_uint64)GPR[sreg+1]; /* insert low order reg value */ - if ((opr & 0xF) == 0xb) { -/*720*/ source = NEGATE32(source); /* make negative for subtract */ - } - dest = s_adfd(td, source, &CC); /* do ADFD */ - - sim_debug(DEBUG_DETAIL, &cpu_dev, - "%s GPR[%d] %08x %08x src %016llx result %016llx\n", - (opr&0xf)==8 ? "ADRFD":"SURFD", reg, GPR[reg], GPR[reg+1], source, dest); - PSD1 &= 0x87FFFFFE; /* clear the old CC's */ - PSD1 |= (CC & 0x78000000); /* update the CC's in the PSD */ - if (CC & CC1BIT) { /* check for arithmetic exception */ - ovr = 1; /* exception */ - /* leave Rd & Rs unchanged if AEXPBIT is set */ - if (MODES & AEXPBIT) { - TRAPME = AEXPCEPT_TRAP; /* trap the system now */ - goto newpsd; /* process the trap */ - } - } - /* AEXPBIT not set, so save the fixed return value */ - /* return result to destination reg */ - GPR[reg+1] = (uint32)(dest & FMASK); /* save the low order reg */ - GPR[reg] = (uint32)((dest>>32) & FMASK);/* save the hi order reg */ - break; - - case 0xA: /* DVRBR */ - /* TODO not on 32/27 */ - if ((MODES & BASEBIT) == 0) /* see if nonbased */ - goto inv; /* invalid instruction in nonbased mode */ - if (reg & 1) { - /* Spec fault if not even reg */ - TRAPME = ADDRSPEC_TRAP; /* bad reg address, error */ - goto newpsd; /* go execute the trap now */ - } - /* get Rs divisor value */ - source = (t_uint64)(GPR[sreg]) | ((GPR[sreg] & FSIGN) ? D32LMASK : 0); - /* merge the dividend regs into the 64bit value */ - dest = (((t_uint64)GPR[reg]) << 32) | ((t_uint64)GPR[reg+1]); - if (source == 0) { - goto doovr4; - break; - } - td = (t_int64)dest % (t_int64)source; /* remainder */ - if (((td & DMSIGN) ^ (dest & DMSIGN)) != 0) /* Fix sign if needed */ - td = NEGATE32(td); /* dividend and remainder must be same sign */ - dest = (t_int64)dest / (t_int64)source; /* now do the divide */ - /* test for overflow */ - if ((dest & D32LMASK) != 0 && (dest & D32LMASK) != D32LMASK) { -doovr4: - ovr = 1; /* the quotient exceeds 31 bit, overflow */ - /* the arithmetic exception will be handled */ - /* after instruction is completed */ - /* check for arithmetic exception trap enabled */ - if (ovr && (MODES & AEXPBIT)) { - TRAPME = AEXPCEPT_TRAP; /* set the trap type */ - } - /* the original regs must be returned unchanged if aexp */ - set_CCs(temp, ovr); /* set the CC's */ - } else { - GPR[reg] = (uint32)(td & FMASK); /* reg gets remainder, reg+1 quotient */ - GPR[reg+1] = (uint32)(dest & FMASK); /* store quotient in reg+1 */ - set_CCs(GPR[reg+1], ovr); /* set the CC's, CC1 = ovr */ - } - break; - - case 0xC: /* DVRFD */ - /* TODO not on 32/27 */ - if ((reg & 1) || (sreg & 1)) { /* see if any odd reg specified */ - TRAPME = ADDRSPEC_TRAP; /* bad reg address, error */ - goto newpsd; /* go execute the trap now */ - } - td = (((t_uint64)GPR[reg]) << 32); /* get upper reg value */ - td |= (t_uint64)GPR[reg+1]; /* insert low order reg value */ - source = (((t_uint64)GPR[sreg]) << 32); /* get upper reg value */ - source |= (t_uint64)GPR[sreg+1]; /* insert low order reg value */ - dest = s_dvfd(td, source, &CC); /* divide double values */ - sim_debug(DEBUG_DETAIL, &cpu_dev, - "DVRFD GPR[%d] %08x %08x src %016llx result %016llx\n", - reg, GPR[reg], GPR[reg+1], source, dest); - PSD1 &= 0x87FFFFFE; /* clear the old CC's */ - PSD1 |= (CC & 0x78000000); /* update the CC's in the PSD */ - if (CC & CC1BIT) { /* check for arithmetic exception */ - ovr = 1; /* exception */ - /* leave Rd & Rs unchanged if AEXPBIT is set */ - if (MODES & AEXPBIT) { - TRAPME = AEXPCEPT_TRAP; /* trap the system now */ - goto newpsd; /* process the trap */ - } - } - /* AEXPBIT not set, so save the fixed return value */ - /* return result to destination reg */ - GPR[reg+1] = (uint32)(dest & FMASK); /* save the low order reg */ - GPR[reg] = (uint32)((dest>>32) & FMASK);/* save the hi order reg */ - break; - - case 0xD: /* FIXD */ - /* dest - reg contents specified by Rd & Rd+1 */ - /* source - reg contents specified by Rs & Rs+1 */ - if (sreg & 1) { - TRAPME = ADDRSPEC_TRAP; /* bad address, error */ - goto newpsd; /* go execute the trap now */ - } - /* merge the sregs into the 64bit value */ - source = (((t_uint64)GPR[sreg]) << 32) | ((t_uint64)GPR[sreg+1]); - /* convert from 64 bit double to 64 bit int */ - dest = s_fixd(source, &CC); - sim_debug(DEBUG_DETAIL, &cpu_dev, - "FIXD GPR[%d] %08x %08x result %016llx\n", - sreg, GPR[sreg], GPR[sreg+1], dest); - PSD1 &= 0x87FFFFFE; /* clear the old CC's */ - PSD1 |= (CC & 0x78000000); /* update the CC's in the PSD */ - if (CC & CC1BIT) { /* check for arithmetic exception */ - ovr = 1; /* exception */ - /* leave Rd & Rs unchanged if AEXPBIT is set */ - if (MODES & AEXPBIT) { - TRAPME = AEXPCEPT_TRAP; /* trap the system now */ - goto newpsd; /* process the trap */ - } - } - /* AEXPBIT not set, so save the fixed return value */ - /* return result to destination reg */ - GPR[reg+1] = (uint32)(dest & FMASK); /* save the low order reg */ - GPR[reg] = (uint32)((dest>>32) & FMASK);/* save the hi order reg */ - break; - - case 0xE: /* MPRFD */ - /* TODO not on 32/27 */ - if ((reg & 1) || (sreg & 1)) { /* see if any odd reg specified */ - TRAPME = ADDRSPEC_TRAP; /* bad reg address, error */ - goto newpsd; /* go execute the trap now */ - } - td = (((t_uint64)GPR[reg]) << 32); /* get upper reg value */ - td |= (t_uint64)GPR[reg+1]; /* insert low order reg value */ - source = (((t_uint64)GPR[sreg]) << 32); /* get upper reg value */ - source |= (t_uint64)GPR[sreg+1]; /* insert low order reg value */ - dest = s_mpfd(td, source, &CC); /* multiply double values */ - sim_debug(DEBUG_DETAIL, &cpu_dev, - "MPRFD GPR[%d] %08x %08x src %016llx result %016llx\n", - reg, GPR[reg], GPR[reg+1], source, dest); - PSD1 &= 0x87FFFFFE; /* clear the old CC's */ - PSD1 |= (CC & 0x78000000); /* update the CC's in the PSD */ - if (CC & CC1BIT) { /* check for arithmetic exception */ - ovr = 1; /* exception */ - /* leave Rd & Rs unchanged if AEXPBIT is set */ - if (MODES & AEXPBIT) { - TRAPME = AEXPCEPT_TRAP; /* trap the system now */ - goto newpsd; /* process the trap */ - } - } - /* AEXPBIT not set, so save the fixed return value */ - /* return result to destination reg */ - GPR[reg+1] = (uint32)(dest & FMASK); /* save the low order reg */ - GPR[reg] = (uint32)((dest>>32) & FMASK);/* save the hi order reg */ - break; - - case 0xF: /* FLTD */ - /* TODO not on 32/27 */ - /* convert from 64 bit integer to 64 bit float */ - if ((reg & 1) || (sreg & 1)) { /* see if any odd reg specified */ - TRAPME = ADDRSPEC_TRAP; /* bad reg address, error */ - goto newpsd; /* go execute the trap now */ - } - source = (((t_uint64)GPR[sreg]) << 32); /* get upper reg value */ - source |= (t_uint64)GPR[sreg+1]; /* insert low order reg value */ - dest = s_fltd(source, &CC); /* do conversion & set CC's */ - sim_debug(DEBUG_DETAIL, &cpu_dev, - "FLTD GPR[%d] %08x %08x result %016llx\n", - sreg, GPR[sreg], GPR[sreg+1], dest); - PSD1 &= 0x87FFFFFE; /* clear the old CC's */ - PSD1 |= (CC & 0x78000000); /* update the CC's in the PSD */ - GPR[reg+1] = (uint32)(dest & FMASK); /* save the low order reg */ - GPR[reg] = (uint32)((dest>>32) & FMASK);/* save the hi order reg */ - break; - } - if (i_flags & SF) { /* see if special processing */ - GPR[reg] = temp; /* temp has destination reg value */ - set_CCs(temp, ovr); /* set the CC's */ - /* the arithmetic exception will be handled */ - /* after instruction is completed */ - /* check for arithmetic exception trap enabled */ - if (ovr && (MODES & AEXPBIT)) { - TRAPME = AEXPCEPT_TRAP; /* set the trap type */ - goto newpsd; /* go execute the trap now */ - } - } + case 0xC: /* TRNM */ /* Transfer register negative masked */ + temp = NEGATE32(addr); /* complement GPR[reg] */ + if (temp == addr) /* check for overflow */ + ovr = 1; /* overflow */ + /* reset ovr if val == 0, not set for DIAGS */ + if ((temp == 0) & ovr) + ovr = 0; + temp &= GPR[4]; /* and with negative reg */ + bc = 1; /* set the CC's */ break; - case 0x3C>>2: /* 0x3C HLF - HLF */ /* SUR and SURM */ - temp = GPR[reg]; /* get negative value to add */ - temp2 = GPR[sreg]; /* get negative value to add */ - addr = NEGATE32(GPR[sreg]); /* reg contents specified by Rs */ - switch(opr & 0xF) { - case 0x0: /* SUR */ - t = (temp & FSIGN) != 0; /* set flag for sign bit not set in temp value */ - t |= ((addr & FSIGN) != 0) ? 2 : 0; /* ditto for the reg value */ - temp = temp + addr; /* add the values */ - /* if both signs are neg and result sign is positive, overflow */ - /* if both signs are pos and result sign is negative, overflow */ - if ((t == 3 && (temp & FSIGN) == 0) || - (t == 0 && (temp & FSIGN) != 0)) - ovr = 1; /* we have an overflow */ - if (addr == FSIGN) - ovr = 1; /* we have an overflow */ - break; + case 0xD: /* XCRM */ /* Exchange registers masked */ + addr &= GPR[4]; /* and Rs with mask reg */ + temp &= GPR[4]; /* and Rd with mask reg */ + GPR[sreg] = temp; /* Rs to get Rd masked value */ + set_CCs(temp, ovr); /* set the CC's from original Rd */ + temp = addr; /* save the Rs value to Rd reg */ + break; - case 0x8: /* SURM */ - t = (temp & FSIGN) != 0; /* set flag for sign bit not set in temp value */ - t |= ((addr & FSIGN) != 0) ? 2 : 0; /* ditto for the reg value */ - temp = temp + addr; /* add the values */ - /* if both signs are neg and result sign is positive, overflow */ - /* if both signs are pos and result sign is negative, overflow */ - if ((t == 3 && (temp & FSIGN) == 0) || - (t == 0 && (temp & FSIGN) != 0)) - ovr = 1; /* we have an overflow */ - temp &= GPR[4]; /* mask the destination reg */ - if (addr == FSIGN) - ovr = 1; /* we have an overflow */ - break; - default: - TRAPME = UNDEFINSTR_TRAP; /* Undefined Instruction Trap */ + case 0xE: /* TRSC */ /* transfer reg to SPAD */ + if ((MODES & PRIVBIT) == 0) { /* must be privileged */ + TRAPME = PRIVVIOL_TRAP; /* set the trap to take */ if ((CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9)) TRAPSTATUS |= BIT0; /* set bit 0 of trap status */ - goto newpsd; /* handle trap */ - break; - } - GPR[reg] = temp; /* save the result */ - set_CCs(temp, ovr); /* set CCs for result */ - /* the arithmetic exception will be handled */ - /* after instruction is completed */ - /* check for arithmetic exception trap enabled */ - if (ovr && (MODES & AEXPBIT)) { - TRAPME = AEXPCEPT_TRAP; /* set the trap type */ - goto newpsd; /* go execute the trap now */ + else + TRAPSTATUS |= BIT19; /* set bit 19 of trap status */ + goto newpsd; /* handle trap */ } + t = (GPR[reg] >> 16) & 0xff; /* get SPAD address from Rd (6-8) */ + temp2 = SPAD[t]; /* get old SPAD data */ + SPAD[t] = GPR[sreg]; /* store Rs into SPAD */ break; - case 0x40>>2: /* 0x40 SCC|SD|HLF - INV */ /* MPR */ - if (MODES & BASEBIT) - goto inv; /* invalid instruction in basemode */ - if (reg & 1) { /* odd reg specified? */ - /* Spec fault */ - /* HACK HACK HACK for DIAGS */ - if (CPU_MODEL <= MODEL_27) { /* DIAG error for 32/27 only */ - if ((PSD1 & 2) == 0) /* if lf hw instruction */ - i_flags &= ~HLF; /* if nop in rt hw, bump pc a word */ - else - PSD1 &= ~3; /* fake out 32/27 diag error */ - } - TRAPME = ADDRSPEC_TRAP; /* bad reg address, error */ - goto newpsd; /* go execute the trap now */ - } - if (opr & 0xf) { /* any subop not zero is error */ - TRAPME = UNDEFINSTR_TRAP; /* Undefined Instruction Trap */ + case 0xF: /* TSCR */ /* Transfer scratchpad to register */ + if ((MODES & PRIVBIT) == 0) { /* must be privileged */ + TRAPME = PRIVVIOL_TRAP; /* set the trap to take */ if ((CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9)) TRAPSTATUS |= BIT0; /* set bit 0 of trap status */ - goto newpsd; /* handle trap */ + else + TRAPSTATUS |= BIT19; /* set bit 19 of trap status */ + goto newpsd; /* handle trap */ } - temp = GPR[reg+1]; /* get multiplicand */ - addr = GPR[sreg]; /* multiplier */ + t = (GPR[sreg] >> 16) & 0xff; /* get SPAD address from Rs (9-11) */ + temp = SPAD[t]; /* get SPAD data into Rd (6-8) */ + break; + } + GPR[reg] = temp; /* save the temp value to Rd reg */ + if (bc) /* set cc's if bc set */ + set_CCs(temp, ovr); /* set the CC's */ + /* the arithmetic exception will be handled */ + /* after instruction is completed */ + /* check for arithmetic exception trap enabled */ + if (ovr && (MODES & AEXPBIT)) { + TRAPME = AEXPCEPT_TRAP; /* set the trap type */ + goto newpsd; /* handle trap */ + } +skipit: + /* for retain, leave PSD2 alone */ + break; - /* change immediate value into a 64 bit value */ + case 0x30>>2: /* 0x30 */ /* CALM */ + /* Process CALM for 32/27 when in left hw, else invalid */ + if ((CPU_MODEL <= MODEL_87) && (CPU_MODEL != MODEL_67)) { + uint32 oldstatus = CPUSTATUS; /* keep for retain blocking state */ + /* DIAG error for 32/27 or 32/87 only */ + if ((PSD1 & 2) != 0) /* is it lf hw instruction */ + goto inv; /* invalid instr if in rt hw */ + addr = SPAD[0xf0]; /* get trap table memory address from SPAD (def 80) */ + if (addr == 0 || addr == 0xffffffff) { /* see if secondary vector table set up */ + TRAPME = ADDRSPEC_TRAP; /* Not setup, error */ + goto newpsd; /* program error */ + } + addr = addr + (0x0A << 2); /* addr has mem addr of CALM trap vector (def A8) */ + t = M[addr >> 2]; /* get the ICB address from memory */ + if (t == 0 || t == 0xffffffff) { /* see if ICB set up */ + TRAPME = ADDRSPEC_TRAP; /* Not setup, error */ + goto newpsd; /* program error */ + } + bc = PSD2 & 0x3ff8; /* get copy of cpix */ + /* this will skip over rt hw instruction if any */ + PSD1 = (PSD1 + 4) | (((PSD1 & 2) >> 1) & 1); /* bump pc by 1 wd */ + M[t>>2] = PSD1 & 0xfffffffe; /* store PSD 1 + 1HW to point to next instruction */ + M[(t>>2)+1] = PSD2; /* store PSD 2 */ + PSD1 = M[(t>>2)+2]; /* get new PSD 1 */ + PSD2 = (M[(t>>2)+3] & ~0x3fff) | bc; /* get new PSD 2 w/old cpix */ + M[(t>>2)+4] = opr & 0x03FF; /* store calm number in bits 6-15 */ + + /* set the mode bits and CCs from the new PSD */ + CC = PSD1 & 0x78000000; /* extract bits 1-4 from PSD1 */ + MODES = PSD1 & 0x87000000; /* extract bits 0, 5, 6, 7 from PSD 1 */ + CPUSTATUS &= ~0x87000000; /* reset bits in CPUSTATUS */ + CPUSTATUS |= MODES; /* now insert into CPUSTATUS */ + + /* set new map mode and interrupt blocking state in CPUSTATUS */ + if (PSD2 & MAPBIT) { + CPUSTATUS |= BIT8; /* set bit 8 of cpu status */ + MODES |= MAPMODE; /* set mapped mode */ + } else + CPUSTATUS &= ~BIT8; /* reset bit 8 of cpu status */ + + /* set interrupt blocking state */ + if ((PSD2 & RETBBIT) == 0) { /* is it retain blocking state */ + if (PSD2 & SETBBIT) { /* no, is it set blocking state */ + CPUSTATUS |= BIT24; /* yes, set blk state in cpu status bit 24 */ + MODES |= BLKMODE; /* set blocked mode */ + } else { + CPUSTATUS &= ~BIT24; /* no, reset blk state in cpu status bit 24 */ + MODES &= ~BLKMODE; /* reset blocked mode */ + irq_pend = 1; /* start scanning interrupts again */ +#ifdef LEAVE_ACTIVE + if (irq_auto) { +/*AIR*/ INTS[irq_auto] &= ~INTS_ACT; /* deactivate specified int level */ +/*AIR*/ SPAD[irq_auto+0x80] &= ~SINT_ACT; /* deactivate in SPAD too */ + sim_debug(DEBUG_IRQ, &cpu_dev, + "<|>IntX deactivate level %02x at CALM PSD1 %08x\n", + irq_auto, PSD1); +/*AIR*/ irq_auto = 0; /* show done processing in blocked mode */ + skipinstr = 1; /* skip interrupt test */ + } +#endif + } + } else { + /* handle retain blocking state */ + PSD2 &= ~RETMBIT; /* turn off retain bit in PSD2 */ + /* set new blocking state in PSD2 */ + PSD2 &= ~(SETBBIT|RETBBIT); /* clear bit 48 & 49 to be unblocked */ + MODES &= ~(BLKMODE|RETMODE); /* reset blocked & retain mode bits */ + if (oldstatus & BIT24) { /* see if old mode is blocked */ + PSD2 |= SETBBIT; /* set to blocked state */ + MODES |= BLKMODE; /* set blocked mode */ + } + } + + SPAD[0xf5] = PSD2; /* save the current PSD2 */ + SPAD[0xf9] = CPUSTATUS; /* save the cpu status in SPAD */ + TRAPME = 0; /* not to be processed as trap */ + goto newpsd; /* new psd loaded */ + } else { +// fprintf(stderr, "got CALM trap\r\n"); + goto inv; /* invalid instr */ + } + break; + + case 0x34>>2: /* 0x34 SD|ADR - inv */ /* LA non-basemode */ + if (MODES & BASEBIT) /* see if based */ + goto inv; /* invalid instruction in based mode */ + if (MODES & EXTDBIT) { /* see if extended mode */ + dest = (t_uint64)(addr&MASK24); /* just pure 24 bit address */ + } else { /* use bits 13-31 */ + dest = (t_uint64)((addr&0x7ffff) | ((FC & 4) << 17)); /* F bit to bit 12 */ + } + break; + + case 0x38>>2: /* 0x38 HLF - HLF */ /* REG - REG floating point */ + switch(opr & 0xF) { + case 0x0: /* ADR */ + temp = GPR[reg]; /* reg contents specified by Rd */ + addr = GPR[sreg]; /* reg contents specified by Rs */ + t = (temp & FSIGN) != 0; /* set flag for sign bit not set in temp value */ + t |= ((addr & FSIGN) != 0) ? 2 : 0; /* ditto for the reg value */ + temp = temp + addr; /* add the values */ + /* if both signs are neg and result sign is positive, overflow */ + /* if both signs are pos and result sign is negative, overflow */ + if ((t == 3 && (temp & FSIGN) == 0) || (t == 0 && (temp & FSIGN) != 0)) { + ovr = 1; /* we have an overflow */ + } + i_flags |= SF; /* special processing */ + break; + + case 0x1: /* ADRFW */ + case 0x3: /* SURFW */ + /* TODO not on 32/27 */ + temp = GPR[reg]; /* reg contents specified by Rd */ + addr = GPR[sreg]; /* reg contents specified by Rs */ + /* temp has Rd (GPR[reg]), addr has Rs (GPR[sreg]) */ + if ((opr & 0xF) == 0x3) { + addr = NEGATE32(addr); /* subtract, so negate source */ + } + temp2 = s_adfw(temp, addr, &CC); /* do ADFW */ + sim_debug(DEBUG_DETAIL, &cpu_dev, + "%s GPR[%d] %08x addr %08x result %08x CC %08x\n", + (opr&0xf)==3 ? "SURFW":"ADRFW", + reg, GPR[reg], GPR[sreg], temp2, CC); + PSD1 &= 0x87FFFFFE; /* clear the old CC's */ + PSD1 |= (CC & 0x78000000); /* update the CC's in the PSD */ + if (CC & CC1BIT) { /* check for arithmetic exception */ + ovr = 1; /* exception */ + /* leave Rd & Rs unchanged if AEXPBIT is set */ + if (MODES & AEXPBIT) { + TRAPME = AEXPCEPT_TRAP; /* trap the system now */ + goto newpsd; /* process the trap */ + } + } + /* AEXPBIT not set, so save the fixed return value */ + /* return result to destination reg */ + GPR[reg] = temp2; /* dest - reg contents specified by Rd */ + break; + + case 0x2: /* MPRBR */ + /* TODO not on 32/27 */ + if ((MODES & BASEBIT) == 0) /* see if nonbased */ + goto inv; /* invalid instruction in nonbased mode */ + if (reg & 1) { + /* Spec fault if not even reg */ + TRAPME = ADDRSPEC_TRAP; /* bad reg address, error */ + goto newpsd; /* go execute the trap now */ + } + temp = GPR[reg+1]; /* get multiplicand */ + addr = GPR[sreg]; /* multiplier */ + + /* change value into a 64 bit value */ dest = ((t_uint64)(addr & FMASK)) | ((addr & FSIGN) ? D32LMASK : 0); source = ((t_uint64)(temp & FMASK)) | ((temp & FSIGN) ? D32LMASK : 0); - dest = dest * source; /* do the multiply */ - dbl = 1; /* double reg save */ + dest = dest * source; /* do the multiply */ + i_flags |= (SD|SCC); /* save dest reg and set CC's */ + dbl = 1; /* double reg save */ break; - case 0x44>>2: /* 0x44 ADR - ADR */ /* DVR */ - /* sreg has Rs */ - if (reg & 1) { - /* Spec fault */ - /* HACK HACK HACK for DIAGS */ - if (CPU_MODEL <= MODEL_27) { /* DIAG error for 32/27 only */ - if ((PSD1 & 2) == 0) /* if lf hw instruction */ - i_flags &= ~HLF; /* if nop in rt hw, bump pc a word */ - else - PSD1 &= ~3; /* fake out 32/27 diag error */ + case 0x4: /* DVRFW */ + /* TODO not on 32/27 */ + temp = GPR[reg]; /* reg contents specified by Rd */ + addr = GPR[sreg]; /* reg contents specified by Rs */ + /* temp has Rd (GPR[reg]), addr has Rs (GPR[sreg]) */ + temp2 = (uint32)s_dvfw(temp, addr, &CC); /* divide reg by sreg */ + sim_debug(DEBUG_DETAIL, &cpu_dev, + "DVRFW GPR[%d] %08x src %08x result %08x\n", + reg, GPR[reg], addr, temp2); + PSD1 &= 0x87FFFFFE; /* clear the old CC's */ + PSD1 |= (CC & 0x78000000); /* update the CC's in the PSD */ + if (CC & CC1BIT) { /* check for arithmetic exception */ + ovr = 1; /* exception */ + /* leave Rd & Rs unchanged if AEXPBIT is set */ + if (MODES & AEXPBIT) { + TRAPME = AEXPCEPT_TRAP; /* trap the system now */ + goto newpsd; /* process the trap */ } - TRAPME = ADDRSPEC_TRAP; /* bad reg address, error */ - goto newpsd; /* go execute the trap now */ } - if (opr & 0xf) { /* any subop not zero is error */ - if ((CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9)) - TRAPSTATUS |= BIT0; /* set bit 0 of trap status */ - TRAPME = UNDEFINSTR_TRAP; /* Undefined Instruction Trap */ - goto newpsd; /* handle trap */ + /* AEXPBIT not set, so save the fixed return value */ + /* return result to destination reg */ + GPR[reg] = temp2; /* dest - reg contents specified by Rd */ + break; + + case 0x5: /* FIXW */ + /* TODO not on 32/27 */ + /* convert from 32 bit float to 32 bit fixed */ + addr = GPR[sreg]; /* reg contents specified by Rs */ + temp2 = s_fixw(addr, &CC); /* do conversion */ + sim_debug(DEBUG_DETAIL, &cpu_dev, + "FIXW GPR[%d] %08x result %08x\n", + sreg, GPR[sreg], temp2); + PSD1 &= 0x87FFFFFE; /* clear the old CC's */ + PSD1 |= (CC & 0x78000000); /* update the CC's in the PSD */ + if (CC & CC1BIT) { /* check for arithmetic exception */ + ovr = 1; /* exception */ + /* leave Rd & Rs unchanged if AEXPBIT is set */ + if (MODES & AEXPBIT) { + TRAPME = AEXPCEPT_TRAP; /* trap the system now */ + goto newpsd; /* process the trap */ + } + } + /* AEXPBIT not set, so save the fixed return value */ + /* return result to destination reg */ + GPR[reg] = temp2; /* dest - reg contents specified by Rd */ + break; /* go set CC's */ + + case 0x6: /* MPRFW */ + /* TODO not on 32/27 */ + temp = GPR[reg]; /* reg contents specified by Rd */ + addr = GPR[sreg]; /* reg contents specified by Rs */ + /* temp has Rd (GPR[reg]), addr has Rs (GPR[sreg]) */ + temp2 = s_mpfw(temp, addr, &CC); /* mult reg by sreg */ + sim_debug(DEBUG_DETAIL, &cpu_dev, + "MPRFW GPR[%d] %08x src %08x result %08x\n", + reg, GPR[reg], addr, temp2); + PSD1 &= 0x87FFFFFE; /* clear the old CC's */ + PSD1 |= (CC & 0x78000000); /* update the CC's in the PSD */ + if (CC & CC1BIT) { /* check for arithmetic exception */ + ovr = 1; /* exception */ + /* leave Rd & Rs unchanged if AEXPBIT is set */ + if (MODES & AEXPBIT) { + TRAPME = AEXPCEPT_TRAP; /* trap the system now */ + goto newpsd; /* process the trap */ + } + } + /* AEXPBIT not set, so save the fixed return value */ + /* return result to destination reg */ + GPR[reg] = temp2; /* dest - reg contents specified by Rd */ + break; + + case 0x7: /* FLTW */ + /* TODO not on 32/27 */ + /* convert from 32 bit integer to 32 bit float */ + addr = GPR[sreg]; /* reg contents specified by Rs */ + GPR[reg] = s_fltw(addr, &CC); /* do conversion & set CC's */ + sim_debug(DEBUG_DETAIL, &cpu_dev, + "FLTW GPR[%d] %08x result %08x\n", + sreg, GPR[sreg], GPR[reg]); + PSD1 &= 0x87FFFFFE; /* clear the old CC's */ + PSD1 |= (CC & 0x78000000); /* update the CC's in the PSD */ + break; + + case 0x8: /* ADRM */ + temp = GPR[reg]; /* reg contents specified by Rd */ + addr = GPR[sreg]; /* reg contents specified by Rs */ + t = (temp & FSIGN) != 0; /* set flag for sign bit not set in temp value */ + t |= ((addr & FSIGN) != 0) ? 2 : 0; /* ditto for the reg value */ + temp = temp + addr; /* add the values */ + /* if both signs are neg and result sign is positive, overflow */ + /* if both signs are pos and result sign is negative, overflow */ + if ((t == 3 && (temp & FSIGN) == 0) || + (t == 0 && (temp & FSIGN) != 0)) + ovr = 1; /* we have an overflow */ + temp &= GPR[4]; /* mask the destination reg */ + i_flags |= SF; /* special processing */ + break; + + case 0x9: /* ADRFD */ + case 0xB: /* SURFD */ + /* TODO not on 32/27 */ + if ((reg & 1) || (sreg & 1)) { /* see if any odd reg specified */ + TRAPME = ADDRSPEC_TRAP; /* bad reg address, error */ + goto newpsd; /* go execute the trap now */ + } + td = (((t_uint64)GPR[reg]) << 32); /* get upper reg value */ + td |= (t_uint64)GPR[reg+1]; /* insert low order reg value */ + source = (((t_uint64)GPR[sreg]) << 32); /* get upper reg value */ + source |= (t_uint64)GPR[sreg+1]; /* insert low order reg value */ + if ((opr & 0xF) == 0xb) { + source = NEGATE32(source); /* make negative for subtract */ + } + dest = s_adfd(td, source, &CC); /* do ADFD */ + + sim_debug(DEBUG_DETAIL, &cpu_dev, + "%s GPR[%d] %08x %08x src %016llx result %016llx\n", + (opr&0xf)==8 ? "ADRFD":"SURFD", reg, GPR[reg], GPR[reg+1], source, dest); + PSD1 &= 0x87FFFFFE; /* clear the old CC's */ + PSD1 |= (CC & 0x78000000); /* update the CC's in the PSD */ + if (CC & CC1BIT) { /* check for arithmetic exception */ + ovr = 1; /* exception */ + /* leave Rd & Rs unchanged if AEXPBIT is set */ + if (MODES & AEXPBIT) { + TRAPME = AEXPCEPT_TRAP; /* trap the system now */ + goto newpsd; /* process the trap */ + } + } + /* AEXPBIT not set, so save the fixed return value */ + /* return result to destination reg */ + GPR[reg+1] = (uint32)(dest & FMASK); /* save the low order reg */ + GPR[reg] = (uint32)((dest>>32) & FMASK);/* save the hi order reg */ + break; + + case 0xA: /* DVRBR */ + /* TODO not on 32/27 */ + if ((MODES & BASEBIT) == 0) /* see if nonbased */ + goto inv; /* invalid instruction in nonbased mode */ + if (reg & 1) { + /* Spec fault if not even reg */ + TRAPME = ADDRSPEC_TRAP; /* bad reg address, error */ + goto newpsd; /* go execute the trap now */ } /* get Rs divisor value */ source = (t_uint64)(GPR[sreg]) | ((GPR[sreg] & FSIGN) ? D32LMASK : 0); /* merge the dividend regs into the 64bit value */ dest = (((t_uint64)GPR[reg]) << 32) | ((t_uint64)GPR[reg+1]); - if (source == 0) - goto doovr3; + if (source == 0) { + goto doovr4; + break; + } td = (t_int64)dest % (t_int64)source; /* remainder */ if (((td & DMSIGN) ^ (dest & DMSIGN)) != 0) /* Fix sign if needed */ - td = NEGATE32(td); /* dividend and remainder must be same sign */ + td = NEGATE32(td); /* dividend and remainder must be same sign */ dest = (t_int64)dest / (t_int64)source; /* now do the divide */ - int64a = dest; - if (int64a < 0) - int64a = -int64a; - if (int64a > 0x7fffffff) /* if more than 31 bits, we have an error */ - goto doovr3; - if (((dest & D32LMASK) != 0 && (dest & D32LMASK) != D32LMASK) || - (((dest & D32LMASK) == D32LMASK) && ((dest & D32RMASK) == 0))) { /* test for overflow */ -doovr3: - dest = (((t_uint64)GPR[reg]) << 32);/* insert upper reg value */ - dest |= (t_uint64)GPR[reg+1]; /* get low order reg value */ - ovr = 1; /* the quotient exceeds 31 bit, overflow */ + /* test for overflow */ + if ((dest & D32LMASK) != 0 && (dest & D32LMASK) != D32LMASK) { +doovr4: + ovr = 1; /* the quotient exceeds 31 bit, overflow */ /* the arithmetic exception will be handled */ /* after instruction is completed */ /* check for arithmetic exception trap enabled */ if (ovr && (MODES & AEXPBIT)) { - TRAPME = AEXPCEPT_TRAP; /* set the trap type */ + TRAPME = AEXPCEPT_TRAP; /* set the trap type */ } /* the original regs must be returned unchanged if aexp */ - CC = CC1BIT; /* set ovr CC bit */ - if (dest == 0) - CC |= CC4BIT; /* dw is zero, so CC4 */ - else - if (dest & DMSIGN) - CC |= CC3BIT; /* it is neg dw, so CC3 */ - else - CC |= CC2BIT; /* then dest > 0, so CC2 */ - PSD1 &= 0x87FFFFFE; /* clear the old CC's from PSD1 */ - PSD1 |= CC; /* update the CC's in the PSD */ + set_CCs(temp, ovr); /* set the CC's */ } else { GPR[reg] = (uint32)(td & FMASK); /* reg gets remainder, reg+1 quotient */ GPR[reg+1] = (uint32)(dest & FMASK); /* store quotient in reg+1 */ - set_CCs(GPR[reg+1], ovr); /* set the CC's, CC1 = ovr */ + set_CCs(GPR[reg+1], ovr); /* set the CC's, CC1 = ovr */ } break; - case 0x48>>2: /* 0x48 INV - INV */ /* unused opcodes */ - case 0x4C>>2: /* 0x4C INV - INV */ /* unused opcodes */ - default: - TRAPME = UNDEFINSTR_TRAP; /* Undefined Instruction Trap */ - if ((CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9)) - TRAPSTATUS |= BIT0; /* set bit 0 of trap status */ - goto newpsd; /* handle trap */ - break; - - case 0x50>>2: /* 0x50 INV - SD|ADR */ /* LA basemode LABRM */ - if ((MODES & BASEBIT) == 0) /* see if nonbased */ - goto inv; /* invalid instruction in nonbased mode */ - dest = (t_uint64)(addr&MASK24); /* just pure 24 bit address */ - break; - - case 0x54>>2: /* 0x54 SM|ADR - INV */ /* (basemode STWBR) */ - if ((MODES & BASEBIT) == 0) /* see if nonbased */ - goto inv; /* invalid instruction in nonbased mode */ - if (FC != 0) { /* word address only */ - TRAPME = ADDRSPEC_TRAP; /* bad reg address, error */ - sim_debug(DEBUG_TRAP, &cpu_dev, - "ADDRSPEC8 OP %04x addr %08x\n", OP, addr); - goto newpsd; /* go execute the trap now */ + case 0xC: /* DVRFD */ + /* TODO not on 32/27 */ + if ((reg & 1) || (sreg & 1)) { /* see if any odd reg specified */ + TRAPME = ADDRSPEC_TRAP; /* bad reg address, error */ + goto newpsd; /* go execute the trap now */ } - dest = BR[reg]; /* save the BR to memory */ - break; - - case 0x58>>2: /* 0x58 SB|ADR - INV */ /* (basemode SUABR and LABR) */ - if ((MODES & BASEBIT) == 0) /* see if nonbased */ - goto inv; /* invalid instruction in nonbased mode */ - if ((FC & 4) == 0) { /* see if SUABR F=0 0x5800 */ - dest = BR[reg] - addr; /* subtract addr from the BR and store back to BR */ - } else { /* LABR if F=1 0x5808 */ - dest = addr; /* addr goes to specified BR */ - } - break; - case 0x5C>>2: /* 0x5C RM|ADR - INV */ /* (basemode LWBR and BSUBM) */ - if ((MODES & BASEBIT) == 0) /* see if nonbased */ - goto inv; /* invalid instruction in nonbased mode */ - if ((FC & 3) != 0) { /* word address only */ - TRAPME = ADDRSPEC_TRAP; /* bad reg address, error */ - sim_debug(DEBUG_TRAP, &cpu_dev, - "ADDRSPEC9 OP %04x addr %08x\n", OP, addr); - goto newpsd; /* go execute the trap now */ - } - if ((FC & 0x4) == 0) { /* this is a LWBR 0x5C00 instruction */ - BR[reg] = (uint32)source; /* load memory location into BR */ - } else - - { /* this is a CALLM/BSUBM instruction */ - /* if Rd field is 0 (reg is b6-8), this is a BSUBM instruction */ - /* otherwise it is a CALLM instruction (Rd != 0) */ - if (reg == 0) { - /* BSUBM instruction */ - uint32 cfp = BR[2]; /* get dword bounded frame pointer from BR2 */ - - if ((BR[2] & 0x7) != 0) { - /* Fault, must be dw bounded address */ - TRAPME = ADDRSPEC_TRAP; /* bad address, error */ - goto newpsd; /* go execute the trap now */ - } - - temp = (PSD1+4) & 0x01fffffe; /* save AEXP bit and PC from PSD1 into frame */ - if ((TRAPME = Mem_write(cfp, &temp))) { /* Save the PSD into memory */ - goto newpsd; /* memory write error or map fault */ - } - - temp = 0x80000000; /* show frame created by BSUBM instr */ - if ((TRAPME = Mem_write(cfp+4, &temp))) { /* Save zero into memory */ - goto newpsd; /* memory write error or map fault */ - } - - temp = addr & 0xfffffe; /* CALL memory address */ - if ((temp & 0x3) != 0) { /* check for word aligned */ - /* Fault, must be word bounded address */ - TRAPME = ADDRSPEC_TRAP; /* bad address, error */ - goto newpsd; /* go execute the trap now */ - } - - if ((TRAPME = Mem_read(temp, &addr))) /* get the word from memory */ - goto newpsd; /* memory read error or map fault */ - - BR[1] = addr; /* effective address contents to BR 1 */ - /* keep bits 0-7 from old PSD */ - PSD1 = ((PSD1 & 0xff000000) | (BR[1] & 0x01fffffe)); /* New PSD address */ - BR[3] = GPR[0]; /* GPR[0] to BR[3] (AP) */ - BR[0] = cfp; /* set current frame pointer into BR[0] */ - i_flags |= BT; /* we changed the PC, so no PC update */ - } else { - /* CALLM instruction */ - - /* get frame pointer from BR2 - 16 words & make it a dword addr */ - uint32 cfp = ((BR[2]-0x40) & 0x00fffff8); - - /* if cfp and cfp+15w are in different maps, then addr exception error */ - if ((cfp & 0xffe000) != ((cfp+0x3f) & 0xffe000)) { - TRAPME = ADDRSPEC_TRAP; /* bad reg address, error */ - goto newpsd; /* go execute the trap now */ - } - - temp = (PSD1+4) & 0x01fffffe; /* save AEXP bit and PC from PSD1 in to frame */ - if ((TRAPME = Mem_write(cfp, &temp))) { /* Save the PSD into memory */ - goto newpsd; /* memory write error or map fault */ - } - - temp = 0x00000000; /* show frame created by CALL instr */ - if ((TRAPME = Mem_write(cfp+4, &temp))) { /* Save zero into memory */ - goto newpsd; /* memory write error or map fault */ - } - - /* save the BRs 0-7 on stack */ - for (ix=0; ix<8; ix++) { - if ((TRAPME = Mem_write(cfp+(4*ix)+8, &BR[ix]))) { /* Save into memory */ - goto newpsd; /* memory write error or map fault */ - } - } - - /* save GPRs 2-7 on stack */ - for (ix=2; ix<8; ix++) { - if ((TRAPME = Mem_write(cfp+(4*ix)+32, &GPR[ix]))) { /* Save into memory */ - goto newpsd; /* memory write error or map fault */ - } - } - - temp = addr & 0xfffffe; /* CALL memory address */ - if ((temp & 0x3) != 0) { /* check for word aligned */ - /* Fault, must be word bounded address */ - TRAPME = ADDRSPEC_TRAP; /* bad address, error */ - goto newpsd; /* go execute the trap now */ - } - - if ((TRAPME = Mem_read(temp, &addr))) /* get the word from memory */ - goto newpsd; /* memory read error or map fault */ - - BR[1] = addr; /* effective address contents to BR 1 */ - /* keep bits 0-6 from old PSD */ - PSD1 = (PSD1 & 0xff000000) | ((BR[1]) & 0x01fffffe); /* New PSD address */ - BR[3] = GPR[reg]; /* Rd to BR 3 (AP) */ - BR[0] = cfp; /* set current frame pointer into BR[0] */ - BR[2] = cfp; /* set current frame pointer into BR[2] */ - i_flags |= BT; /* we changed the PC, so no PC update */ + td = (((t_uint64)GPR[reg]) << 32); /* get upper reg value */ + td |= (t_uint64)GPR[reg+1]; /* insert low order reg value */ + source = (((t_uint64)GPR[sreg]) << 32); /* get upper reg value */ + source |= (t_uint64)GPR[sreg+1]; /* insert low order reg value */ + dest = s_dvfd(td, source, &CC); /* divide double values */ + sim_debug(DEBUG_DETAIL, &cpu_dev, + "DVRFD GPR[%d] %08x %08x src %016llx result %016llx\n", + reg, GPR[reg], GPR[reg+1], source, dest); + PSD1 &= 0x87FFFFFE; /* clear the old CC's */ + PSD1 |= (CC & 0x78000000); /* update the CC's in the PSD */ + if (CC & CC1BIT) { /* check for arithmetic exception */ + ovr = 1; /* exception */ + /* leave Rd & Rs unchanged if AEXPBIT is set */ + if (MODES & AEXPBIT) { + TRAPME = AEXPCEPT_TRAP; /* trap the system now */ + goto newpsd; /* process the trap */ } } - break; - - case 0x60>>2: /* 0x60 HLF - INV */ /* NOR Rd,Rs */ - if ((MODES & BASEBIT)) { /* only for nonbased mode */ - TRAPME = UNDEFINSTR_TRAP; /* Undefined Instruction Trap */ - if ((CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9)) - TRAPSTATUS |= BIT0; /* set bit 0 of trap status */ - goto newpsd; /* handle trap */ - } - if (opr & 0xf) { /* any subop not zero is error */ - TRAPME = UNDEFINSTR_TRAP; /* Undefined Instruction Trap */ - if ((CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9)) - TRAPSTATUS |= BIT0; /* set bit 0 of trap status */ - goto newpsd; /* handle trap */ - } - /* exponent must not be zero or all 1's */ - /* normalize the value Rd in GPR[reg] and put exponent into Rs GPR[sreg] */ - temp = s_nor(GPR[reg], &GPR[sreg]); - sim_debug(DEBUG_DETAIL, &cpu_dev, - "NOR GPR[%d] %08x result %08x exp %02x\n", - reg, GPR[reg], temp, GPR[sreg]); - GPR[reg] = temp; - break; - - case 0x64>>2: /* 0x64 SD|HLF - INV */ /* NORD */ - if ((MODES & BASEBIT)) { /* only for nonbased mode */ - TRAPME = UNDEFINSTR_TRAP; /* Undefined Instruction Trap */ - if ((CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9)) - TRAPSTATUS |= BIT0; /* set bit 0 of trap status */ - goto newpsd; /* handle trap */ - } - if (reg & 1) { /* see if odd reg specified */ - TRAPME = ADDRSPEC_TRAP; /* bad reg address, error */ - goto newpsd; /* go execute the trap now */ - } - if (opr & 0xf) { /* any subop not zero is error */ - TRAPME = UNDEFINSTR_TRAP; /* Undefined Instruction Trap */ - if ((CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9)) - TRAPSTATUS |= BIT0; /* set bit 0 of trap status */ - goto newpsd; /* handle trap */ - } - /* shift until upper 5 bits are neither 0 or all 1's */ - /* merge the GPR[reg] & GPR[reg+1] into a 64bit value */ - td = (((t_uint64)GPR[reg]) << 32) | ((t_uint64)GPR[reg+1]); - /* normalize the value Rd in GPR[reg] and put exponent into Rs GPR[sreg] */ - dest = s_nord(td, &GPR[sreg]); - sim_debug(DEBUG_DETAIL, &cpu_dev, - "NORD GPR[%d] %08x %08x result %016llx exp %02x\n", - reg, GPR[reg], GPR[reg+1], dest, GPR[sreg]); + /* AEXPBIT not set, so save the fixed return value */ + /* return result to destination reg */ GPR[reg+1] = (uint32)(dest & FMASK); /* save the low order reg */ GPR[reg] = (uint32)((dest>>32) & FMASK);/* save the hi order reg */ break; - case 0x68>>2: /* 0x68 HLF - INV */ /* non basemode SCZ */ - if (MODES & BASEBIT) - goto inv; /* invalid instruction */ - if (opr & 0xf) { /* any subop not zero is error */ - TRAPME = UNDEFINSTR_TRAP; /* Undefined Instruction Trap */ - if ((CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9)) - TRAPSTATUS |= BIT0; /* set bit 0 of trap status */ - goto newpsd; /* handle trap */ + case 0xD: /* FIXD */ + /* dest - reg contents specified by Rd & Rd+1 */ + /* source - reg contents specified by Rs & Rs+1 */ + if (sreg & 1) { + TRAPME = ADDRSPEC_TRAP; /* bad address, error */ + goto newpsd; /* go execute the trap now */ } - goto sacz; /* use basemode sacz instruction */ - - case 0x6C>>2: /* 0x6C HLF - INV */ /* non basemode SRA & SLA */ - if (MODES & BASEBIT) - goto inv; /* invalid instruction */ - bc = opr & 0x1f; /* get bit shift count */ - temp = GPR[reg]; /* get reg value to shift */ - t = temp & FSIGN; /* sign value */ - if (opr & 0x0040) { /* is this SLA */ - ovr = 0; /* set ovr off */ - for (ix=0; ix>= 1; /* shift bit 0 right one bit */ - temp |= t; /* restore original sign bit */ - } - GPR[reg] = temp; /* save the new value */ - } - break; - - case 0x70>>2: /* 0x70 SD|HLF - INV */ /* non-basemode SRL & SLL */ - if (MODES & BASEBIT) - goto inv; /* invalid instruction in basemode */ - bc = opr & 0x1f; /* get bit shift count */ - if (opr & 0x0040) /* is this SLL, bit 9 set */ - GPR[reg] <<= bc; /* shift left #bits */ - else - GPR[reg] >>= bc; /* shift right #bits */ - break; - - case 0x74>>2: /* 0x74 SD|HLF - INV */ /* non-basemode SRC & SLC */ - if (MODES & BASEBIT) - goto inv; /* invalid instruction in basemode */ - bc = opr & 0x1f; /* get bit shift count */ - temp = GPR[reg]; /* get reg value to shift */ - if (opr & 0x0040) { /* is this SLC, bit 9 set */ - for (ix=0; ix>= 1; /* shift the bit out */ - if (t) - temp |= BIT0; /* put in new sign bit */ + /* merge the sregs into the 64bit value */ + source = (((t_uint64)GPR[sreg]) << 32) | ((t_uint64)GPR[sreg+1]); + /* convert from 64 bit double to 64 bit int */ + dest = s_fixd(source, &CC); + sim_debug(DEBUG_DETAIL, &cpu_dev, + "FIXD GPR[%d] %08x %08x result %016llx\n", + sreg, GPR[sreg], GPR[sreg+1], dest); + PSD1 &= 0x87FFFFFE; /* clear the old CC's */ + PSD1 |= (CC & 0x78000000); /* update the CC's in the PSD */ + if (CC & CC1BIT) { /* check for arithmetic exception */ + ovr = 1; /* exception */ + /* leave Rd & Rs unchanged if AEXPBIT is set */ + if (MODES & AEXPBIT) { + TRAPME = AEXPCEPT_TRAP; /* trap the system now */ + goto newpsd; /* process the trap */ } } - GPR[reg] = temp; /* shift result */ - break; - - case 0x78>>2: /* 0x78 HLF - INV */ /* non-basemode SRAD & SLAD */ - if (MODES & BASEBIT) /* Base mode? */ - goto inv; /* invalid instruction in basemode */ - if (reg & 1) { /* see if odd reg specified */ - TRAPME = ADDRSPEC_TRAP; /* bad reg address, error */ - goto newpsd; /* go execute the trap now */ - } - bc = opr & 0x1f; /* get bit shift count */ - dest = (t_uint64)GPR[reg+1]; /* get low order reg value */ - dest |= (((t_uint64)GPR[reg]) << 32); /* insert upper reg value */ - source = dest & DMSIGN; /* 64 bit sign value */ - if (opr & 0x0040) { /* is this SLAD */ - ovr = 0; /* set ovr off */ - for (ix=0; ix>32) & FMASK);/* save the hi order reg */ - PSD1 &= 0x87FFFFFE; /* clear the old CC's */ - if (ovr) - PSD1 |= BIT1; /* CC1 in PSD */ - /* the arithmetic exception will be handled */ - /* after instruction is completed */ - /* check for arithmetic exception trap enabled */ - if (ovr && (MODES & AEXPBIT)) { - TRAPME = AEXPCEPT_TRAP; /* set the trap type */ - goto newpsd; /* go execute the trap now */ - } - } else { /* this is a SRAD */ - for (ix=0; ix>= 1; /* shift bit 0 right one bit */ - dest |= source; /* restore original sign bit */ - } - GPR[reg+1] = (uint32)(dest & FMASK); /* save the low order reg */ - GPR[reg] = (uint32)((dest>>32) & FMASK);/* save the hi order reg */ - } - break; - - case 0x7C>>2: /* 0x7C HLF - INV */ /* non-basemode SRLD & SLLD */ - if (MODES & BASEBIT) - goto inv; /* invalid instruction in basemode */ - if (reg & 1) { /* see if odd reg specified */ - TRAPME = ADDRSPEC_TRAP; /* bad reg address, error */ - goto newpsd; /* go execute the trap now */ - } - dest = (t_uint64)GPR[reg+1]; /* get low order reg value */ - dest |= (((t_uint64)GPR[reg]) << 32); /* insert upper reg value */ - bc = opr & 0x1f; /* get bit shift count */ - if (opr & 0x0040) /* is this SLL, bit 9 set */ - dest <<= bc; /* shift left #bits */ - else - dest >>= bc; /* shift right #bits */ + /* AEXPBIT not set, so save the fixed return value */ + /* return result to destination reg */ GPR[reg+1] = (uint32)(dest & FMASK); /* save the low order reg */ GPR[reg] = (uint32)((dest>>32) & FMASK);/* save the hi order reg */ break; - case 0x80>>2: /* 0x80 SD|ADR - SD|ADR */ /* LEAR */ - /* convert address to real physical address */ - TRAPME = RealAddr(addr, &temp, &t, MEM_RD); - // diag allows any addr if mapped - if (TRAPME != ALLOK) { - sim_debug(DEBUG_TRAP, &cpu_dev, - "At LEAR with TRAPME %04x addr %08x\n", TRAPME, addr); - goto newpsd; /* memory read error or map fault */ + case 0xE: /* MPRFD */ + /* TODO not on 32/27 */ + if ((reg & 1) || (sreg & 1)) { /* see if any odd reg specified */ + TRAPME = ADDRSPEC_TRAP; /* bad reg address, error */ + goto newpsd; /* go execute the trap now */ } - /* set access bit for mapped addresses */ - if ((CPU_MODEL >= MODEL_V6) && (MODES & MAPMODE)) { - uint32 map, mix, nix, msdl, mpl, mmap; - - nix = (addr >> 13) & 0x7ff; /* get 11 bit map value */ - /* check our access to the memory */ - switch (t & 0x0e) { - case 0x0: case 0x2: - /* O/S or user has no read/execute access, do protection violation */ - sim_debug(DEBUG_TRAP, &cpu_dev, - "LEAR readI protect error @ %06x prot %02x modes %08x page %04x\n", - addr, t, MODES, nix); - if (CPU_MODEL == MODEL_V9) - TRAPSTATUS |= BIT1; /* set bit 1 of trap status */ - else - TRAPSTATUS |= BIT12; /* set bit 12 of trap status */ - return MPVIOL; /* return memory protection violation */ - case 0x4: case 0x6: case 0x8: case 0xc: case 0xa: case 0xe: - /* O/S or user has read/execute access, no protection violation */ - sim_debug(DEBUG_DETAIL, &cpu_dev, - "LEAR readJ protect is ok @ %06x prot %02x modes %08x page %04x\n", - addr, t, MODES, nix); - } - /* we have read access, so go set the access bit in the map entry */ - mpl = SPAD[0xf3]; /* get mpl from spad address */ - if (nix < BPIX) { - mix = nix; /* get map index in memory */ - msdl = RMW(mpl+4); /* get mpl entry for O/S */ - } else { - mix = nix-BPIX; /* get map index in memory */ - msdl = RMW(mpl+CPIX+4); /* get mpl entry for given CPIX */ - } - mmap = RMH(msdl+(mix<<1)); /* map content from memory */ - map = RMR((nix<<1)); /* read the map cache contents */ - if (((map & 0x800) == 0)) { /* see if access bit is already on */ - mmap |= 0x800; /* set the accessed bit in the map cache entry */ - map |= 0x800; /* set the accessed bit in the memory map entry */ - WMR((nix<<1), map); /* store the map reg contents into cache */ - TLB[nix] |= 0x0c000000; /* set the accessed & hit bits in TLB too */ - WMH(msdl+(mix<<1), mmap); /* save modified memory map with access bit set */ - sim_debug(DEBUG_EXP, &cpu_dev, - "LEAR Laddr %06x page %04x set access bit TLB %08x map %04x nmap %04x\n", - addr, nix, TLB[nix], map, mmap); + td = (((t_uint64)GPR[reg]) << 32); /* get upper reg value */ + td |= (t_uint64)GPR[reg+1]; /* insert low order reg value */ + source = (((t_uint64)GPR[sreg]) << 32); /* get upper reg value */ + source |= (t_uint64)GPR[sreg+1]; /* insert low order reg value */ + dest = s_mpfd(td, source, &CC); /* multiply double values */ + sim_debug(DEBUG_DETAIL, &cpu_dev, + "MPRFD GPR[%d] %08x %08x src %016llx result %016llx\n", + reg, GPR[reg], GPR[reg+1], source, dest); + PSD1 &= 0x87FFFFFE; /* clear the old CC's */ + PSD1 |= (CC & 0x78000000); /* update the CC's in the PSD */ + if (CC & CC1BIT) { /* check for arithmetic exception */ + ovr = 1; /* exception */ + /* leave Rd & Rs unchanged if AEXPBIT is set */ + if (MODES & AEXPBIT) { + TRAPME = AEXPCEPT_TRAP; /* trap the system now */ + goto newpsd; /* process the trap */ } } - - /* OS code says F bit is not transferred, so just ignore it */ - /* DIAGS needs it, so put it back */ - if (FC & 4) /* see if F bit was set */ - temp |= 0x01000000; /* set bit 7 of address */ - dest = temp; /* put in dest to go out */ + /* AEXPBIT not set, so save the fixed return value */ + /* return result to destination reg */ + GPR[reg+1] = (uint32)(dest & FMASK); /* save the low order reg */ + GPR[reg] = (uint32)((dest>>32) & FMASK);/* save the hi order reg */ break; - case 0x84>>2: /* 0x84 SD|RR|RNX|ADR - SD|RNX|ADR */ /* ANMx */ - td = dest & source; /* DO ANMX */ - CC = 0; - switch(FC) { /* adjust for hw or bytes */ - case 4: case 5: case 6: case 7: /* byte address */ - /* ANMB */ - td &= 0xff; /* mask out right most byte */ - dest &= 0xffffff00; /* make place for byte */ - if (td == 0) - CC |= CC4BIT; /* byte is zero, so CC4 */ - else - CC |= CC2BIT; /* then td > 0, so CC2 */ - break; - case 1: /* left halfword addr */ - case 3: /* right halfword addr */ - /* ANMH */ - td &= RMASK; /* mask out right most 16 bits */ - dest &= LMASK; /* make place for halfword */ - if (td == 0) - CC |= CC4BIT; /* hw is zero, so CC4 */ - else - CC |= CC2BIT; /* then td > 0, so CC2 */ - break; - case 0: /* 32 bit word */ - /* ANMW */ - td &= D32RMASK; /* mask out right most 32 bits */ - dest = 0; /* make place for 64 bits */ - if (td == 0) - CC |= CC4BIT; /* word is zero, so CC4 */ - else - if (td & 0x80000000) - CC |= CC3BIT; /* it is neg wd, so CC3 */ - else - CC |= CC2BIT; /* then td > 0, so CC2 */ - break; - case 2: /* 64 bit double */ - /* ANMD */ - dest = 0; /* make place for 64 bits */ - if (td == 0) - CC |= CC4BIT; /* dw is zero, so CC4 */ - else - if (td & DMSIGN) - CC |= CC3BIT; /* it is neg dw, so CC3 */ - else - CC |= CC2BIT; /* then td > 0, so CC2 */ - break; + case 0xF: /* FLTD */ + /* TODO not on 32/27 */ + /* convert from 64 bit integer to 64 bit float */ + if ((reg & 1) || (sreg & 1)) { /* see if any odd reg specified */ + TRAPME = ADDRSPEC_TRAP; /* bad reg address, error */ + goto newpsd; /* go execute the trap now */ } - dest |= td; /* insert result into dest */ - if (FC != 2) /* do not sign extend DW */ - if (dest & 0x80000000) /* see if we need to sign extend */ - dest |= D32LMASK; /* force upper word to all ones */ - PSD1 &= 0x87FFFFFE; /* clear the old CC's from PSD1 */ - PSD1 |= CC; /* update the CC's in the PSD */ + source = (((t_uint64)GPR[sreg]) << 32); /* get upper reg value */ + source |= (t_uint64)GPR[sreg+1]; /* insert low order reg value */ + dest = s_fltd(source, &CC); /* do conversion & set CC's */ + sim_debug(DEBUG_DETAIL, &cpu_dev, + "FLTD GPR[%d] %08x %08x result %016llx\n", + sreg, GPR[sreg], GPR[sreg+1], dest); + PSD1 &= 0x87FFFFFE; /* clear the old CC's */ + PSD1 |= (CC & 0x78000000); /* update the CC's in the PSD */ + GPR[reg+1] = (uint32)(dest & FMASK); /* save the low order reg */ + GPR[reg] = (uint32)((dest>>32) & FMASK);/* save the hi order reg */ break; - - case 0x88>>2: /* 0x88 SD|RR|RNX|ADR - SD|RNX|ADR */ /* ORMx */ - td = dest | source; /* DO ORMX */ -meoa: /* merge point for eor, and, or */ - CC = 0; - switch(FC) { /* adjust for hw or bytes */ - case 4: case 5: case 6: case 7: /* byte address */ - /* ORMB */ - td &= 0xff; /* mask out right most byte */ - dest &= 0xffffff00; /* make place for byte */ - dest |= td; /* insert result into dest */ - if (dest == 0) - CC |= CC4BIT; /* byte is zero, so CC4 */ - else - if (dest & MSIGN) { - CC |= CC3BIT; /* assume negative */ - dest |= D32LMASK; /* force upper word to all ones */ - } - else - CC |= CC2BIT; /* then td > 0, so CC2 */ - break; - case 1: /* left halfword addr */ - case 3: /* right halfword addr */ - /* ORMH */ - td &= RMASK; /* mask out right most 16 bits */ - dest &= LMASK; /* make place for halfword */ - dest |= td; /* insert result into dest */ - if (dest == 0) - CC |= CC4BIT; /* byte is zero, so CC4 */ - else - if (dest & MSIGN) { - CC |= CC3BIT; /* assume negative */ - dest |= D32LMASK; /* force upper word to all ones */ - } - else - CC |= CC2BIT; /* then td > 0, so CC2 */ - break; - case 0: /* 32 bit word */ - /* ORMW */ - td &= D32RMASK; /* mask out right most 32 bits */ - dest = 0; /* make place for 64 bits */ - dest |= td; /* insert result into dest */ - if (dest == 0) - CC |= CC4BIT; /* byte is zero, so CC4 */ - else - if (dest & MSIGN) { - CC |= CC3BIT; /* assume negative */ - dest |= D32LMASK; /* force upper word to all ones */ - } - else - CC |= CC2BIT; /* then td > 0, so CC2 */ - break; - case 2: /* 64 bit double */ - /* ORMD */ - dest = 0; /* make place for 64 bits */ - dest |= td; /* insert result into dest */ - if (dest == 0) - CC |= CC4BIT; /* byte is zero, so CC4 */ - else - if (dest & DMSIGN) - CC |= CC3BIT; /* assume negative */ - else - CC |= CC2BIT; /* then td > 0, so CC2 */ - break; - } - PSD1 &= 0x87FFFFFE; /* clear the old CC's from PSD1 */ - PSD1 |= CC; /* update the CC's in the PSD */ - break; - - case 0x8C>>2: /* 0x8C SD|RR|RNX|ADR - SD|RNX|ADR */ /* EOMx */ - /* must special handle because we are getting bit difference */ - /* for word, halfword, & byte zero the upper 32 bits of dest */ - /* Diags require CC's to be set on result value of byte, hw, wd, or dw */ - td = dest ^ source; /* DO EOMX */ - goto meoa; - break; - - case 0x90>>2: /* 0x90 SCC|RR|RM|ADR - RM|ADR */ /* CAMx */ - if (dbl == 0) { - int32a = dest & D32RMASK; /* mask out right most 32 bits */ - int32b = source & D32RMASK; /* mask out right most 32 bits */ - int32c = int32a - int32b; /* signed diff */ - td = int32c; - if (int32a > int32b) dest = 1; - else if (int32a == int32b) dest = 0; - else dest = -1; - } else { - int64a = dest; /* mask out right most 32 bits */ - int64b = source; /* mask out right most 32 bits */ - int64c = int64a - int64b; /* signed diff */ - td = int64c; - if (int64a > int64b) dest = 1; - else if (int64a == int64b) dest = 0; - else dest = -1; - } - break; - - case 0x94>>2: /* 0x94 RR|RM|ADR - RM|ADR */ /* CMMx */ - /* CMMD needs both regs to be masked with R4 */ - if (dbl) { - /* we need to and both regs with R4 */ - t_uint64 nm = (((t_uint64)GPR[4]) << 32) | (((t_uint64)GPR[4]) & D32RMASK); - td = dest; /* save dest */ - dest ^= source; - dest &= nm; /* mask both regs with reg 4 contents */ - } else { - td = dest; /* save dest */ - dest ^= source; /* <= 32 bits, so just do lower 32 bits */ - dest &= (((t_uint64)GPR[4]) & D32RMASK); /* mask with reg 4 contents */ - } - CC = 0; - if (dest == 0ll) - CC |= CC4BIT; - PSD1 &= 0x87FFFFFE; /* clear the old CC's from PSD1 */ - PSD1 |= CC; /* update the CC's in the PSD */ - break; - - case 0x98>>2: /* 0x98 ADR - ADR */ /* SBM */ - if ((FC & 04) == 0) { - /* Fault, f-bit must be set for SBM instruction */ - TRAPME = ADDRSPEC_TRAP; /* bad reg address, error */ - goto newpsd; /* go execute the trap now */ - } - if ((TRAPME = Mem_read(addr, &temp))) /* get the word from memory */ - goto newpsd; /* memory read error or map fault */ - - t = (PSD1 & 0x70000000) >> 1; /* get old CC bits 1-3 into CCs 2-4*/ - /* use C bits and bits 6-8 (reg) to generate shift bit count */ - bc = ((FC & 3) << 3) | reg; /* get # bits to shift right */ - bc = BIT0 >> bc; /* make a bit mask of bit number */ - PSD1 &= 0x87FFFFFE; /* clear the old CC's from PSD1 */ - if (temp & bc) /* test the bit in memory */ - t |= CC1BIT; /* set CC1 to the bit value */ - PSD1 |= t; /* update the CC's in the PSD */ - temp |= bc; /* set the bit in temp */ - if ((TRAPME = Mem_write(addr, &temp))) { /* put word back into memory */ - goto newpsd; /* memory write error or map fault */ - } - break; - - case 0x9C>>2: /* 0x9C ADR - ADR */ /* ZBM */ - if ((FC & 04) == 0) { - /* Fault, byte address not allowed */ - TRAPME = ADDRSPEC_TRAP; /* bad reg address, error */ - goto newpsd; /* go execute the trap now */ - } - if ((TRAPME = Mem_read(addr, &temp))) /* get the word from memory */ - goto newpsd; /* memory read error or map fault */ - - t = (PSD1 & 0x70000000) >> 1; /* get old CC bits 1-3 into CCs 2-4*/ - /* use C bits and bits 6-8 (reg) to generate shift bit count */ - bc = ((FC & 3) << 3) | reg; /* get # bits to shift right */ - bc = BIT0 >> bc; /* make a bit mask of bit number */ - PSD1 &= 0x87FFFFFE; /* clear the old CC's from PSD1 */ - if (temp & bc) /* test the bit in memory */ - t |= CC1BIT; /* set CC1 to the bit value */ - PSD1 |= t; /* update the CC's in the PSD */ - temp &= ~bc; /* reset the bit in temp */ - if ((TRAPME = Mem_write(addr, &temp))) { /* put word into memory */ - goto newpsd; /* memory write error or map fault */ - } - break; - - case 0xA0>>2: /* 0xA0 ADR - ADR */ /* ABM */ - if ((FC & 04) == 0) { - /* Fault, byte address not allowed */ - TRAPME = ADDRSPEC_TRAP; /* bad reg address, error */ - goto newpsd; /* go execute the trap now */ - } - if ((TRAPME = Mem_read(addr, &temp))) /* get the word from memory */ - goto newpsd; /* memory read error or map fault */ - - /* use C bits and bits 6-8 (reg) to generate shift bit count */ - bc = ((FC & 3) << 3) | reg; /* get # bits to shift right */ - bc = BIT0 >> bc; /* make a bit mask of bit number */ - t = (temp & FSIGN) != 0; /* set flag for sign bit not set in temp value */ - t |= ((bc & FSIGN) != 0) ? 2 : 0; /* ditto for the bit value */ - temp += bc; /* add the bit value to the reg */ - /* if both signs are neg and result sign is positive, overflow */ - /* if both signs are pos and result sign is negative, overflow */ - if ((t == 3 && (temp & FSIGN) == 0) || - (t == 0 && (temp & FSIGN) != 0)) { - ovr = 1; /* we have an overflow */ - } - set_CCs(temp, ovr); /* set the CC's, CC1 = ovr */ - if ((TRAPME = Mem_write(addr, &temp))) { /* put word into memory */ - goto newpsd; /* memory write error or map fault */ - } + } + if (i_flags & SF) { /* see if special processing */ + GPR[reg] = temp; /* temp has destination reg value */ + set_CCs(temp, ovr); /* set the CC's */ /* the arithmetic exception will be handled */ /* after instruction is completed */ /* check for arithmetic exception trap enabled */ if (ovr && (MODES & AEXPBIT)) { - TRAPME = AEXPCEPT_TRAP; /* set the trap type */ - goto newpsd; /* handle trap */ + TRAPME = AEXPCEPT_TRAP; /* set the trap type */ + goto newpsd; /* go execute the trap now */ + } + } + break; + + case 0x3C>>2: /* 0x3C HLF - HLF */ /* SUR and SURM */ + temp = GPR[reg]; /* get negative value to add */ + temp2 = GPR[sreg]; /* get negative value to add */ + addr = NEGATE32(GPR[sreg]); /* reg contents specified by Rs */ + switch(opr & 0xF) { + case 0x0: /* SUR */ + t = (temp & FSIGN) != 0; /* set flag for sign bit not set in temp value */ + t |= ((addr & FSIGN) != 0) ? 2 : 0; /* ditto for the reg value */ + temp = temp + addr; /* add the values */ + /* if both signs are neg and result sign is positive, overflow */ + /* if both signs are pos and result sign is negative, overflow */ + if ((t == 3 && (temp & FSIGN) == 0) || + (t == 0 && (temp & FSIGN) != 0)) + ovr = 1; /* we have an overflow */ + if (addr == FSIGN) + ovr = 1; /* we have an overflow */ + break; + + case 0x8: /* SURM */ + t = (temp & FSIGN) != 0; /* set flag for sign bit not set in temp value */ + t |= ((addr & FSIGN) != 0) ? 2 : 0; /* ditto for the reg value */ + temp = temp + addr; /* add the values */ + /* if both signs are neg and result sign is positive, overflow */ + /* if both signs are pos and result sign is negative, overflow */ + if ((t == 3 && (temp & FSIGN) == 0) || + (t == 0 && (temp & FSIGN) != 0)) + ovr = 1; /* we have an overflow */ + temp &= GPR[4]; /* mask the destination reg */ + if (addr == FSIGN) + ovr = 1; /* we have an overflow */ + break; + default: + TRAPME = UNDEFINSTR_TRAP; /* Undefined Instruction Trap */ + if ((CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9)) + TRAPSTATUS |= BIT0; /* set bit 0 of trap status */ + goto newpsd; /* handle trap */ + break; + } + GPR[reg] = temp; /* save the result */ + set_CCs(temp, ovr); /* set CCs for result */ + /* the arithmetic exception will be handled */ + /* after instruction is completed */ + /* check for arithmetic exception trap enabled */ + if (ovr && (MODES & AEXPBIT)) { + TRAPME = AEXPCEPT_TRAP; /* set the trap type */ + goto newpsd; /* go execute the trap now */ + } + break; + + case 0x40>>2: /* 0x40 SCC|SD|HLF - INV */ /* MPR */ + if (MODES & BASEBIT) + goto inv; /* invalid instruction in basemode */ + if (reg & 1) { /* odd reg specified? */ + /* Spec fault */ + /* HACK HACK HACK for DIAGS */ + if (CPU_MODEL <= MODEL_27) { /* DIAG error for 32/27 only */ + if ((PSD1 & 2) == 0) /* if lf hw instruction */ + i_flags &= ~HLF; /* if nop in rt hw, bump pc a word */ + else + PSD1 &= ~3; /* fake out 32/27 diag error */ + } + TRAPME = ADDRSPEC_TRAP; /* bad reg address, error */ + goto newpsd; /* go execute the trap now */ + } + if (opr & 0xf) { /* any subop not zero is error */ + TRAPME = UNDEFINSTR_TRAP; /* Undefined Instruction Trap */ + if ((CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9)) + TRAPSTATUS |= BIT0; /* set bit 0 of trap status */ + goto newpsd; /* handle trap */ + } + temp = GPR[reg+1]; /* get multiplicand */ + addr = GPR[sreg]; /* multiplier */ + + /* change immediate value into a 64 bit value */ + dest = ((t_uint64)(addr & FMASK)) | ((addr & FSIGN) ? D32LMASK : 0); + source = ((t_uint64)(temp & FMASK)) | ((temp & FSIGN) ? D32LMASK : 0); + dest = dest * source; /* do the multiply */ + dbl = 1; /* double reg save */ + break; + + case 0x44>>2: /* 0x44 ADR - ADR */ /* DVR */ + /* sreg has Rs */ + if (reg & 1) { + /* Spec fault */ + /* HACK HACK HACK for DIAGS */ + if (CPU_MODEL <= MODEL_27) { /* DIAG error for 32/27 only */ + if ((PSD1 & 2) == 0) /* if lf hw instruction */ + i_flags &= ~HLF; /* if nop in rt hw, bump pc a word */ + else + PSD1 &= ~3; /* fake out 32/27 diag error */ + } + TRAPME = ADDRSPEC_TRAP; /* bad reg address, error */ + goto newpsd; /* go execute the trap now */ + } + if (opr & 0xf) { /* any subop not zero is error */ + if ((CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9)) + TRAPSTATUS |= BIT0; /* set bit 0 of trap status */ + TRAPME = UNDEFINSTR_TRAP; /* Undefined Instruction Trap */ + goto newpsd; /* handle trap */ + } + /* get Rs divisor value */ + source = (t_uint64)(GPR[sreg]) | ((GPR[sreg] & FSIGN) ? D32LMASK : 0); + /* merge the dividend regs into the 64bit value */ + dest = (((t_uint64)GPR[reg]) << 32) | ((t_uint64)GPR[reg+1]); + if (source == 0) + goto doovr3; + td = (t_int64)dest % (t_int64)source; /* remainder */ + if (((td & DMSIGN) ^ (dest & DMSIGN)) != 0) /* Fix sign if needed */ + td = NEGATE32(td); /* dividend and remainder must be same sign */ + dest = (t_int64)dest / (t_int64)source; /* now do the divide */ + int64a = dest; + if (int64a < 0) + int64a = -int64a; + if (int64a > 0x7fffffff) /* if more than 31 bits, we have an error */ + goto doovr3; + if (((dest & D32LMASK) != 0 && (dest & D32LMASK) != D32LMASK) || + (((dest & D32LMASK) == D32LMASK) && ((dest & D32RMASK) == 0))) { /* test for overflow */ +doovr3: + dest = (((t_uint64)GPR[reg]) << 32);/* insert upper reg value */ + dest |= (t_uint64)GPR[reg+1]; /* get low order reg value */ + ovr = 1; /* the quotient exceeds 31 bit, overflow */ + /* the arithmetic exception will be handled */ + /* after instruction is completed */ + /* check for arithmetic exception trap enabled */ + if (ovr && (MODES & AEXPBIT)) { + TRAPME = AEXPCEPT_TRAP; /* set the trap type */ + } + /* the original regs must be returned unchanged if aexp */ + CC = CC1BIT; /* set ovr CC bit */ + if (dest == 0) + CC |= CC4BIT; /* dw is zero, so CC4 */ + else + if (dest & DMSIGN) + CC |= CC3BIT; /* it is neg dw, so CC3 */ + else + CC |= CC2BIT; /* then dest > 0, so CC2 */ + PSD1 &= 0x87FFFFFE; /* clear the old CC's from PSD1 */ + PSD1 |= CC; /* update the CC's in the PSD */ + } else { + GPR[reg] = (uint32)(td & FMASK); /* reg gets remainder, reg+1 quotient */ + GPR[reg+1] = (uint32)(dest & FMASK); /* store quotient in reg+1 */ + set_CCs(GPR[reg+1], ovr); /* set the CC's, CC1 = ovr */ + } + break; + + case 0x48>>2: /* 0x48 INV - INV */ /* unused opcodes */ + case 0x4C>>2: /* 0x4C INV - INV */ /* unused opcodes */ + default: + TRAPME = UNDEFINSTR_TRAP; /* Undefined Instruction Trap */ + if ((CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9)) + TRAPSTATUS |= BIT0; /* set bit 0 of trap status */ + goto newpsd; /* handle trap */ + break; + + case 0x50>>2: /* 0x50 INV - SD|ADR */ /* LA basemode LABRM */ + if ((MODES & BASEBIT) == 0) /* see if nonbased */ + goto inv; /* invalid instruction in nonbased mode */ + dest = (t_uint64)(addr&MASK24); /* just pure 24 bit address */ + break; + + case 0x54>>2: /* 0x54 SM|ADR - INV */ /* (basemode STWBR) */ + if ((MODES & BASEBIT) == 0) /* see if nonbased */ + goto inv; /* invalid instruction in nonbased mode */ + if (FC != 0) { /* word address only */ + TRAPME = ADDRSPEC_TRAP; /* bad reg address, error */ + sim_debug(DEBUG_TRAP, &cpu_dev, + "ADDRSPEC8 OP %04x addr %08x\n", OP, addr); + goto newpsd; /* go execute the trap now */ + } + dest = BR[reg]; /* save the BR to memory */ + break; + + case 0x58>>2: /* 0x58 SB|ADR - INV */ /* (basemode SUABR and LABR) */ + if ((MODES & BASEBIT) == 0) /* see if nonbased */ + goto inv; /* invalid instruction in nonbased mode */ + if ((FC & 4) == 0) { /* see if SUABR F=0 0x5800 */ + dest = BR[reg] - addr; /* subtract addr from the BR and store back to BR */ + } else { /* LABR if F=1 0x5808 */ + dest = addr; /* addr goes to specified BR */ + } + break; + + case 0x5C>>2: /* 0x5C RM|ADR - INV */ /* (basemode LWBR and BSUBM) */ + if ((MODES & BASEBIT) == 0) /* see if nonbased */ + goto inv; /* invalid instruction in nonbased mode */ + if ((FC & 3) != 0) { /* word address only */ + TRAPME = ADDRSPEC_TRAP; /* bad reg address, error */ + sim_debug(DEBUG_TRAP, &cpu_dev, + "ADDRSPEC9 OP %04x addr %08x\n", OP, addr); + goto newpsd; /* go execute the trap now */ + } + if ((FC & 0x4) == 0) { /* this is a LWBR 0x5C00 instruction */ + BR[reg] = (uint32)source; /* load memory location into BR */ + } else + { /* this is a CALLM/BSUBM instruction */ + /* if Rd field is 0 (reg is b6-8), this is a BSUBM instruction */ + /* otherwise it is a CALLM instruction (Rd != 0) */ + if (reg == 0) { + /* BSUBM instruction */ + uint32 cfp = BR[2]; /* get dword bounded frame pointer from BR2 */ + + if ((BR[2] & 0x7) != 0) { + /* Fault, must be dw bounded address */ + TRAPME = ADDRSPEC_TRAP; /* bad address, error */ + goto newpsd; /* go execute the trap now */ + } + + temp = (PSD1+4) & 0x01fffffe; /* save AEXP bit and PC from PSD1 into frame */ + if ((TRAPME = Mem_write(cfp, &temp))) { /* Save the PSD into memory */ + goto newpsd; /* memory write error or map fault */ + } + + temp = 0x80000000; /* show frame created by BSUBM instr */ + if ((TRAPME = Mem_write(cfp+4, &temp))) { /* Save zero into memory */ + goto newpsd; /* memory write error or map fault */ + } + + temp = addr & 0xfffffe; /* CALL memory address */ + if ((temp & 0x3) != 0) { /* check for word aligned */ + /* Fault, must be word bounded address */ + TRAPME = ADDRSPEC_TRAP; /* bad address, error */ + goto newpsd; /* go execute the trap now */ + } + + if ((TRAPME = Mem_read(temp, &addr))) /* get the word from memory */ + goto newpsd; /* memory read error or map fault */ + + BR[1] = addr; /* effective address contents to BR 1 */ + /* keep bits 0-7 from old PSD */ + PSD1 = ((PSD1 & 0xff000000) | (BR[1] & 0x01fffffe)); /* New PSD address */ + BR[3] = GPR[0]; /* GPR[0] to BR[3] (AP) */ + BR[0] = cfp; /* set current frame pointer into BR[0] */ + i_flags |= BT; /* we changed the PC, so no PC update */ + } else { + /* CALLM instruction */ + + /* get frame pointer from BR2 - 16 words & make it a dword addr */ + uint32 cfp = ((BR[2]-0x40) & 0x00fffff8); + + /* if cfp and cfp+15w are in different maps, then addr exception error */ + if ((cfp & 0xffe000) != ((cfp+0x3f) & 0xffe000)) { + TRAPME = ADDRSPEC_TRAP; /* bad reg address, error */ + goto newpsd; /* go execute the trap now */ + } + + temp = (PSD1+4) & 0x01fffffe; /* save AEXP bit and PC from PSD1 in to frame */ + if ((TRAPME = Mem_write(cfp, &temp))) { /* Save the PSD into memory */ + goto newpsd; /* memory write error or map fault */ + } + + temp = 0x00000000; /* show frame created by CALL instr */ + if ((TRAPME = Mem_write(cfp+4, &temp))) { /* Save zero into memory */ + goto newpsd; /* memory write error or map fault */ + } + + /* save the BRs 0-7 on stack */ + for (ix=0; ix<8; ix++) { + if ((TRAPME = Mem_write(cfp+(4*ix)+8, &BR[ix]))) { /* Save into memory */ + goto newpsd; /* memory write error or map fault */ + } + } + + /* save GPRs 2-7 on stack */ + for (ix=2; ix<8; ix++) { + if ((TRAPME = Mem_write(cfp+(4*ix)+32, &GPR[ix]))) { /* Save into memory */ + goto newpsd; /* memory write error or map fault */ + } + } + + temp = addr & 0xfffffe; /* CALL memory address */ + if ((temp & 0x3) != 0) { /* check for word aligned */ + /* Fault, must be word bounded address */ + TRAPME = ADDRSPEC_TRAP; /* bad address, error */ + goto newpsd; /* go execute the trap now */ + } + + if ((TRAPME = Mem_read(temp, &addr))) /* get the word from memory */ + goto newpsd; /* memory read error or map fault */ + + BR[1] = addr; /* effective address contents to BR 1 */ + /* keep bits 0-6 from old PSD */ + PSD1 = (PSD1 & 0xff000000) | ((BR[1]) & 0x01fffffe); /* New PSD address */ + BR[3] = GPR[reg]; /* Rd to BR 3 (AP) */ + BR[0] = cfp; /* set current frame pointer into BR[0] */ + BR[2] = cfp; /* set current frame pointer into BR[2] */ + i_flags |= BT; /* we changed the PC, so no PC update */ + } + } + break; + + case 0x60>>2: /* 0x60 HLF - INV */ /* NOR Rd,Rs */ + if ((MODES & BASEBIT)) { /* only for nonbased mode */ + TRAPME = UNDEFINSTR_TRAP; /* Undefined Instruction Trap */ + if ((CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9)) + TRAPSTATUS |= BIT0; /* set bit 0 of trap status */ + goto newpsd; /* handle trap */ + } + if (opr & 0xf) { /* any subop not zero is error */ + TRAPME = UNDEFINSTR_TRAP; /* Undefined Instruction Trap */ + if ((CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9)) + TRAPSTATUS |= BIT0; /* set bit 0 of trap status */ + goto newpsd; /* handle trap */ + } + /* exponent must not be zero or all 1's */ + /* normalize the value Rd in GPR[reg] and put exponent into Rs GPR[sreg] */ + temp = s_nor(GPR[reg], &GPR[sreg]); + sim_debug(DEBUG_DETAIL, &cpu_dev, + "NOR GPR[%d] %08x result %08x exp %02x\n", + reg, GPR[reg], temp, GPR[sreg]); + GPR[reg] = temp; + break; + + case 0x64>>2: /* 0x64 SD|HLF - INV */ /* NORD */ + if ((MODES & BASEBIT)) { /* only for nonbased mode */ + TRAPME = UNDEFINSTR_TRAP; /* Undefined Instruction Trap */ + if ((CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9)) + TRAPSTATUS |= BIT0; /* set bit 0 of trap status */ + goto newpsd; /* handle trap */ + } + if (reg & 1) { /* see if odd reg specified */ + TRAPME = ADDRSPEC_TRAP; /* bad reg address, error */ + goto newpsd; /* go execute the trap now */ + } + if (opr & 0xf) { /* any subop not zero is error */ + TRAPME = UNDEFINSTR_TRAP; /* Undefined Instruction Trap */ + if ((CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9)) + TRAPSTATUS |= BIT0; /* set bit 0 of trap status */ + goto newpsd; /* handle trap */ + } + /* shift until upper 5 bits are neither 0 or all 1's */ + /* merge the GPR[reg] & GPR[reg+1] into a 64bit value */ + td = (((t_uint64)GPR[reg]) << 32) | ((t_uint64)GPR[reg+1]); + /* normalize the value Rd in GPR[reg] and put exponent into Rs GPR[sreg] */ + dest = s_nord(td, &GPR[sreg]); + sim_debug(DEBUG_DETAIL, &cpu_dev, + "NORD GPR[%d] %08x %08x result %016llx exp %02x\n", + reg, GPR[reg], GPR[reg+1], dest, GPR[sreg]); + GPR[reg+1] = (uint32)(dest & FMASK); /* save the low order reg */ + GPR[reg] = (uint32)((dest>>32) & FMASK);/* save the hi order reg */ + break; + + case 0x68>>2: /* 0x68 HLF - INV */ /* non basemode SCZ */ + if (MODES & BASEBIT) + goto inv; /* invalid instruction */ + if (opr & 0xf) { /* any subop not zero is error */ + TRAPME = UNDEFINSTR_TRAP; /* Undefined Instruction Trap */ + if ((CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9)) + TRAPSTATUS |= BIT0; /* set bit 0 of trap status */ + goto newpsd; /* handle trap */ + } + goto sacz; /* use basemode sacz instruction */ + + case 0x6C>>2: /* 0x6C HLF - INV */ /* non basemode SRA & SLA */ + if (MODES & BASEBIT) + goto inv; /* invalid instruction */ + bc = opr & 0x1f; /* get bit shift count */ + temp = GPR[reg]; /* get reg value to shift */ + t = temp & FSIGN; /* sign value */ + if (opr & 0x0040) { /* is this SLA */ + ovr = 0; /* set ovr off */ + for (ix=0; ix>= 1; /* shift bit 0 right one bit */ + temp |= t; /* restore original sign bit */ + } + GPR[reg] = temp; /* save the new value */ + } + break; + + case 0x70>>2: /* 0x70 SD|HLF - INV */ /* non-basemode SRL & SLL */ + if (MODES & BASEBIT) + goto inv; /* invalid instruction in basemode */ + bc = opr & 0x1f; /* get bit shift count */ + if (opr & 0x0040) /* is this SLL, bit 9 set */ + GPR[reg] <<= bc; /* shift left #bits */ + else + GPR[reg] >>= bc; /* shift right #bits */ + break; + + case 0x74>>2: /* 0x74 SD|HLF - INV */ /* non-basemode SRC & SLC */ + if (MODES & BASEBIT) + goto inv; /* invalid instruction in basemode */ + bc = opr & 0x1f; /* get bit shift count */ + temp = GPR[reg]; /* get reg value to shift */ + if (opr & 0x0040) { /* is this SLC, bit 9 set */ + for (ix=0; ix>= 1; /* shift the bit out */ + if (t) + temp |= BIT0; /* put in new sign bit */ + } + } + GPR[reg] = temp; /* shift result */ + break; + + case 0x78>>2: /* 0x78 HLF - INV */ /* non-basemode SRAD & SLAD */ + if (MODES & BASEBIT) /* Base mode? */ + goto inv; /* invalid instruction in basemode */ + if (reg & 1) { /* see if odd reg specified */ + TRAPME = ADDRSPEC_TRAP; /* bad reg address, error */ + goto newpsd; /* go execute the trap now */ + } + bc = opr & 0x1f; /* get bit shift count */ + dest = (t_uint64)GPR[reg+1]; /* get low order reg value */ + dest |= (((t_uint64)GPR[reg]) << 32); /* insert upper reg value */ + source = dest & DMSIGN; /* 64 bit sign value */ + if (opr & 0x0040) { /* is this SLAD */ + ovr = 0; /* set ovr off */ + for (ix=0; ix>32) & FMASK);/* save the hi order reg */ + PSD1 &= 0x87FFFFFE; /* clear the old CC's */ + if (ovr) + PSD1 |= BIT1; /* CC1 in PSD */ + /* the arithmetic exception will be handled */ + /* after instruction is completed */ + /* check for arithmetic exception trap enabled */ + if (ovr && (MODES & AEXPBIT)) { + TRAPME = AEXPCEPT_TRAP; /* set the trap type */ + goto newpsd; /* go execute the trap now */ + } + } else { /* this is a SRAD */ + for (ix=0; ix>= 1; /* shift bit 0 right one bit */ + dest |= source; /* restore original sign bit */ + } + GPR[reg+1] = (uint32)(dest & FMASK); /* save the low order reg */ + GPR[reg] = (uint32)((dest>>32) & FMASK);/* save the hi order reg */ + } + break; + + case 0x7C>>2: /* 0x7C HLF - INV */ /* non-basemode SRLD & SLLD */ + if (MODES & BASEBIT) + goto inv; /* invalid instruction in basemode */ + if (reg & 1) { /* see if odd reg specified */ + TRAPME = ADDRSPEC_TRAP; /* bad reg address, error */ + goto newpsd; /* go execute the trap now */ + } + dest = (t_uint64)GPR[reg+1]; /* get low order reg value */ + dest |= (((t_uint64)GPR[reg]) << 32); /* insert upper reg value */ + bc = opr & 0x1f; /* get bit shift count */ + if (opr & 0x0040) /* is this SLL, bit 9 set */ + dest <<= bc; /* shift left #bits */ + else + dest >>= bc; /* shift right #bits */ + GPR[reg+1] = (uint32)(dest & FMASK); /* save the low order reg */ + GPR[reg] = (uint32)((dest>>32) & FMASK);/* save the hi order reg */ + break; + + case 0x80>>2: /* 0x80 SD|ADR - SD|ADR */ /* LEAR */ + /* convert address to real physical address */ + TRAPME = RealAddr(addr, &temp, &t, MEM_RD); + // diag allows any addr if mapped + if (TRAPME != ALLOK) { + sim_debug(DEBUG_TRAP, &cpu_dev, + "At LEAR with TRAPME %04x addr %08x\n", TRAPME, addr); + goto newpsd; /* memory read error or map fault */ + } + /* set access bit for mapped addresses */ + if ((CPU_MODEL >= MODEL_V6) && (MODES & MAPMODE)) { + uint32 map, mix, nix, msdl, mpl, mmap; + + nix = (addr >> 13) & 0x7ff; /* get 11 bit map value */ + /* check our access to the memory */ + switch (t & 0x0e) { + case 0x0: case 0x2: + /* O/S or user has no read/execute access, do protection violation */ + sim_debug(DEBUG_TRAP, &cpu_dev, + "LEAR readI protect error @ %06x prot %02x modes %08x page %04x\n", + addr, t, MODES, nix); + if (CPU_MODEL == MODEL_V9) + TRAPSTATUS |= BIT1; /* set bit 1 of trap status */ + else + TRAPSTATUS |= BIT12; /* set bit 12 of trap status */ + return MPVIOL; /* return memory protection violation */ + case 0x4: case 0x6: case 0x8: case 0xc: case 0xa: case 0xe: + /* O/S or user has read/execute access, no protection violation */ + sim_debug(DEBUG_DETAIL, &cpu_dev, + "LEAR readJ protect is ok @ %06x prot %02x modes %08x page %04x\n", + addr, t, MODES, nix); + } + /* we have read access, so go set the access bit in the map entry */ + mpl = SPAD[0xf3]; /* get mpl from spad address */ + if (nix < BPIX) { + mix = nix; /* get map index in memory */ + msdl = RMW(mpl+4); /* get mpl entry for O/S */ + } else { + mix = nix-BPIX; /* get map index in memory */ + msdl = RMW(mpl+CPIX+4); /* get mpl entry for given CPIX */ + } + mmap = RMH(msdl+(mix<<1)); /* map content from memory */ + map = RMR((nix<<1)); /* read the map cache contents */ + if (((map & 0x800) == 0)) { /* see if access bit is already on */ + mmap |= 0x800; /* set the accessed bit in the map cache entry */ + map |= 0x800; /* set the accessed bit in the memory map entry */ + WMR((nix<<1), map); /* store the map reg contents into cache */ + TLB[nix] |= 0x0c000000; /* set the accessed & hit bits in TLB too */ + WMH(msdl+(mix<<1), mmap); /* save modified memory map with access bit set */ + sim_debug(DEBUG_EXP, &cpu_dev, + "LEAR Laddr %06x page %04x set access bit TLB %08x map %04x nmap %04x\n", + addr, nix, TLB[nix], map, mmap); + } + } + + /* OS code says F bit is not transferred, so just ignore it */ + /* DIAGS needs it, so put it back */ + if (FC & 4) /* see if F bit was set */ + temp |= 0x01000000; /* set bit 7 of address */ + dest = temp; /* put in dest to go out */ + break; + + case 0x84>>2: /* 0x84 SD|RR|RNX|ADR - SD|RNX|ADR */ /* ANMx */ + td = dest & source; /* DO ANMX */ + CC = 0; + switch(FC) { /* adjust for hw or bytes */ + case 4: case 5: case 6: case 7: /* byte address */ + /* ANMB */ + td &= 0xff; /* mask out right most byte */ + dest &= 0xffffff00; /* make place for byte */ + if (td == 0) + CC |= CC4BIT; /* byte is zero, so CC4 */ + else + CC |= CC2BIT; /* then td > 0, so CC2 */ + break; + case 1: /* left halfword addr */ + case 3: /* right halfword addr */ + /* ANMH */ + td &= RMASK; /* mask out right most 16 bits */ + dest &= LMASK; /* make place for halfword */ + if (td == 0) + CC |= CC4BIT; /* hw is zero, so CC4 */ + else + CC |= CC2BIT; /* then td > 0, so CC2 */ + break; + case 0: /* 32 bit word */ + /* ANMW */ + td &= D32RMASK; /* mask out right most 32 bits */ + dest = 0; /* make place for 64 bits */ + if (td == 0) + CC |= CC4BIT; /* word is zero, so CC4 */ + else + if (td & 0x80000000) + CC |= CC3BIT; /* it is neg wd, so CC3 */ + else + CC |= CC2BIT; /* then td > 0, so CC2 */ + break; + case 2: /* 64 bit double */ + /* ANMD */ + dest = 0; /* make place for 64 bits */ + if (td == 0) + CC |= CC4BIT; /* dw is zero, so CC4 */ + else + if (td & DMSIGN) + CC |= CC3BIT; /* it is neg dw, so CC3 */ + else + CC |= CC2BIT; /* then td > 0, so CC2 */ + break; + } + dest |= td; /* insert result into dest */ + if (FC != 2) { /* do not sign extend DW */ + if (dest & 0x80000000) /* see if we need to sign extend */ + dest |= D32LMASK; /* force upper word to all ones */ + } + PSD1 &= 0x87FFFFFE; /* clear the old CC's from PSD1 */ + PSD1 |= CC; /* update the CC's in the PSD */ + break; + + case 0x88>>2: /* 0x88 SD|RR|RNX|ADR - SD|RNX|ADR */ /* ORMx */ + td = dest | source; /* DO ORMX */ +meoa: /* merge point for eor, and, or */ + CC = 0; + switch(FC) { /* adjust for hw or bytes */ + case 4: case 5: case 6: case 7: /* byte address */ + /* ORMB */ + td &= 0xff; /* mask out right most byte */ + dest &= 0xffffff00; /* make place for byte */ + dest |= td; /* insert result into dest */ + if (dest == 0) + CC |= CC4BIT; /* byte is zero, so CC4 */ + else + if (dest & MSIGN) { + CC |= CC3BIT; /* assume negative */ + dest |= D32LMASK; /* force upper word to all ones */ + } + else + CC |= CC2BIT; /* then td > 0, so CC2 */ + break; + case 1: /* left halfword addr */ + case 3: /* right halfword addr */ + /* ORMH */ + td &= RMASK; /* mask out right most 16 bits */ + dest &= LMASK; /* make place for halfword */ + dest |= td; /* insert result into dest */ + if (dest == 0) + CC |= CC4BIT; /* byte is zero, so CC4 */ + else + if (dest & MSIGN) { + CC |= CC3BIT; /* assume negative */ + dest |= D32LMASK; /* force upper word to all ones */ + } + else + CC |= CC2BIT; /* then td > 0, so CC2 */ + break; + case 0: /* 32 bit word */ + /* ORMW */ + td &= D32RMASK; /* mask out right most 32 bits */ + dest = 0; /* make place for 64 bits */ + dest |= td; /* insert result into dest */ + if (dest == 0) + CC |= CC4BIT; /* byte is zero, so CC4 */ + else + if (dest & MSIGN) { + CC |= CC3BIT; /* assume negative */ + dest |= D32LMASK; /* force upper word to all ones */ + } + else + CC |= CC2BIT; /* then td > 0, so CC2 */ + break; + case 2: /* 64 bit double */ + /* ORMD */ + dest = 0; /* make place for 64 bits */ + dest |= td; /* insert result into dest */ + if (dest == 0) + CC |= CC4BIT; /* byte is zero, so CC4 */ + else + if (dest & DMSIGN) + CC |= CC3BIT; /* assume negative */ + else + CC |= CC2BIT; /* then td > 0, so CC2 */ + break; + } + PSD1 &= 0x87FFFFFE; /* clear the old CC's from PSD1 */ + PSD1 |= CC; /* update the CC's in the PSD */ + break; + + case 0x8C>>2: /* 0x8C SD|RR|RNX|ADR - SD|RNX|ADR */ /* EOMx */ + /* must special handle because we are getting bit difference */ + /* for word, halfword, & byte zero the upper 32 bits of dest */ + /* Diags require CC's to be set on result value of byte, hw, wd, or dw */ + td = dest ^ source; /* DO EOMX */ + goto meoa; + break; + + case 0x90>>2: /* 0x90 SCC|RR|RM|ADR - RM|ADR */ /* CAMx */ + if (dbl == 0) { + int32a = dest & D32RMASK; /* mask out right most 32 bits */ + int32b = source & D32RMASK; /* mask out right most 32 bits */ + int32c = int32a - int32b; /* signed diff */ + td = int32c; + if (int32a > int32b) dest = 1; + else + if (int32a == int32b) dest = 0; + else dest = -1; + } else { + int64a = dest; /* mask out right most 32 bits */ + int64b = source; /* mask out right most 32 bits */ + int64c = int64a - int64b; /* signed diff */ + td = int64c; + if (int64a > int64b) dest = 1; + else + if (int64a == int64b) dest = 0; + else dest = -1; + } + break; + + case 0x94>>2: /* 0x94 RR|RM|ADR - RM|ADR */ /* CMMx */ + /* CMMD needs both regs to be masked with R4 */ + if (dbl) { + /* we need to and both regs with R4 */ + t_uint64 nm = (((t_uint64)GPR[4]) << 32) | (((t_uint64)GPR[4]) & D32RMASK); + td = dest; /* save dest */ + dest ^= source; + dest &= nm; /* mask both regs with reg 4 contents */ + } else { + td = dest; /* save dest */ + dest ^= source; /* <= 32 bits, so just do lower 32 bits */ + dest &= (((t_uint64)GPR[4]) & D32RMASK); /* mask with reg 4 contents */ + } + CC = 0; + if (dest == 0ll) + CC |= CC4BIT; + PSD1 &= 0x87FFFFFE; /* clear the old CC's from PSD1 */ + PSD1 |= CC; /* update the CC's in the PSD */ + break; + + case 0x98>>2: /* 0x98 ADR - ADR */ /* SBM */ + if ((FC & 04) == 0) { + /* Fault, f-bit must be set for SBM instruction */ + TRAPME = ADDRSPEC_TRAP; /* bad reg address, error */ + goto newpsd; /* go execute the trap now */ + } + if ((TRAPME = Mem_read(addr, &temp))) /* get the word from memory */ + goto newpsd; /* memory read error or map fault */ + + t = (PSD1 & 0x70000000) >> 1; /* get old CC bits 1-3 into CCs 2-4*/ + /* use C bits and bits 6-8 (reg) to generate shift bit count */ + bc = ((FC & 3) << 3) | reg; /* get # bits to shift right */ + bc = BIT0 >> bc; /* make a bit mask of bit number */ + PSD1 &= 0x87FFFFFE; /* clear the old CC's from PSD1 */ + if (temp & bc) /* test the bit in memory */ + t |= CC1BIT; /* set CC1 to the bit value */ + PSD1 |= t; /* update the CC's in the PSD */ + temp |= bc; /* set the bit in temp */ + if ((TRAPME = Mem_write(addr, &temp))) { /* put word back into memory */ + goto newpsd; /* memory write error or map fault */ + } + break; + + case 0x9C>>2: /* 0x9C ADR - ADR */ /* ZBM */ + if ((FC & 04) == 0) { + /* Fault, byte address not allowed */ + TRAPME = ADDRSPEC_TRAP; /* bad reg address, error */ + goto newpsd; /* go execute the trap now */ + } + if ((TRAPME = Mem_read(addr, &temp))) /* get the word from memory */ + goto newpsd; /* memory read error or map fault */ + + t = (PSD1 & 0x70000000) >> 1; /* get old CC bits 1-3 into CCs 2-4*/ + /* use C bits and bits 6-8 (reg) to generate shift bit count */ + bc = ((FC & 3) << 3) | reg; /* get # bits to shift right */ + bc = BIT0 >> bc; /* make a bit mask of bit number */ + PSD1 &= 0x87FFFFFE; /* clear the old CC's from PSD1 */ + if (temp & bc) /* test the bit in memory */ + t |= CC1BIT; /* set CC1 to the bit value */ + PSD1 |= t; /* update the CC's in the PSD */ + temp &= ~bc; /* reset the bit in temp */ + if ((TRAPME = Mem_write(addr, &temp))) { /* put word into memory */ + goto newpsd; /* memory write error or map fault */ + } + break; + + case 0xA0>>2: /* 0xA0 ADR - ADR */ /* ABM */ + if ((FC & 04) == 0) { + /* Fault, byte address not allowed */ + TRAPME = ADDRSPEC_TRAP; /* bad reg address, error */ + goto newpsd; /* go execute the trap now */ + } + if ((TRAPME = Mem_read(addr, &temp))) /* get the word from memory */ + goto newpsd; /* memory read error or map fault */ + + /* use C bits and bits 6-8 (reg) to generate shift bit count */ + bc = ((FC & 3) << 3) | reg; /* get # bits to shift right */ + bc = BIT0 >> bc; /* make a bit mask of bit number */ + t = (temp & FSIGN) != 0; /* set flag for sign bit not set in temp value */ + t |= ((bc & FSIGN) != 0) ? 2 : 0; /* ditto for the bit value */ + temp += bc; /* add the bit value to the reg */ + /* if both signs are neg and result sign is positive, overflow */ + /* if both signs are pos and result sign is negative, overflow */ + if ((t == 3 && (temp & FSIGN) == 0) || + (t == 0 && (temp & FSIGN) != 0)) { + ovr = 1; /* we have an overflow */ + } + set_CCs(temp, ovr); /* set the CC's, CC1 = ovr */ + if ((TRAPME = Mem_write(addr, &temp))) { /* put word into memory */ + goto newpsd; /* memory write error or map fault */ + } + /* the arithmetic exception will be handled */ + /* after instruction is completed */ + /* check for arithmetic exception trap enabled */ + if (ovr && (MODES & AEXPBIT)) { + TRAPME = AEXPCEPT_TRAP; /* set the trap type */ + goto newpsd; /* handle trap */ + } + break; + + case 0xA4>>2: /* 0xA4 ADR - ADR */ /* TBM */ + if ((FC & 04) == 0) { + /* Fault, byte address not allowed */ + TRAPME = ADDRSPEC_TRAP; /* bad reg address, error */ + goto newpsd; /* go execute the trap now */ + } + if ((TRAPME = Mem_read(addr, &temp))) /* get the word from memory */ + goto newpsd; /* memory read error or map fault */ + + t = (PSD1 & 0x70000000) >> 1; /* get old CC bits 1-3 into CCs 2-4*/ + /* use C bits and bits 6-8 (reg) to generate shift bit count */ + bc = ((FC & 3) << 3) | reg; /* get # bits to shift right */ + bc = BIT0 >> bc; /* make a bit mask of bit number */ + PSD1 &= 0x87FFFFFE; /* clear the old CC's from PSD1 */ + if (temp & bc) /* test the bit in memory */ + t |= CC1BIT; /* set CC1 to the bit value */ + PSD1 |= t; /* update the CC's in the PSD */ + break; + + case 0xA8>>2: /* 0xA8 RM|ADR - RM|ADR */ /* EXM */ + if ((FC & 04) != 0 || FC == 2) { /* can not be byte or doubleword */ + /* Fault */ + TRAPME = ADDRSPEC_TRAP; /* bad reg address, error */ + goto newpsd; /* go execute the trap now */ + } + if ((TRAPME = Mem_read(addr, &temp))) { /* get the word from memory */ + if (CPU_MODEL == MODEL_V9) /* V9 wants bit0 set in pfault */ + if (TRAPME == DMDPG) /* demand page request */ + pfault |= 0x80000000; /* set instruction fetch paging error */ + goto newpsd; /* memory read error or map fault */ + } + + IR = temp; /* get instruction from memory */ + if (FC == 3) /* see if right halfword specified */ + IR <<= 16; /* move over the HW instruction */ +#ifdef DIAG_SAYS_OK_TO_EXECUTE_ANOTHER_EXECUTE + if ((IR & 0xFC7F0000) == 0xC8070000 || /* No EXR target */ + (IR & 0xFF800000) == 0xA8000000 || /* No EXM target */ + (IR & 0xFC000000) == 0x80000000) { +#else + /* 32/67 diag says execute of execute is OK */ + if ((IR & 0xFC000000) == 0x80000000) { +#endif + /* Fault, attempt to execute another EXR, EXRR, EXM, or LEAR */ + goto inv; /* invalid instruction */ + } + EXM_EXR = 4; /* set PC increment for EXM */ + + OPSD1 &= 0x87FFFFFE; /* clear the old PSD CC's */ + OPSD1 |= PSD1 & 0x78000000; /* update the CC's in the old PSD */ + /* TODO Update other history information for this instruction */ + if (hst_lnt) { + hst[hst_p].opsd1 = OPSD1; /* update the CC in opsd1 */ + hst[hst_p].npsd1 = PSD1; /* save new psd1 */ + hst[hst_p].npsd2 = PSD2; /* save new psd2 */ + hst[hst_p].modes = MODES; /* save current mode bits */ + for (ix=0; ix<8; ix++) { + hst[hst_p].reg[ix] = GPR[ix]; /* save reg */ + hst[hst_p].reg[ix+8] = BR[ix]; /* save breg */ + } + } + + /* DEBUG_INST support code */ + OPSD1 &= 0x87FFFFFE; /* clear the old CC's */ + OPSD1 |= PSD1 & 0x78000000; /* update the CC's in the PSD */ + /* output mapped/unmapped */ + if (MODES & BASEBIT) { + if (MODES & MAPMODE) + sim_debug(DEBUG_INST, &cpu_dev, "BM%.8x %.8x %.8x ", OPSD1, PSD2, OIR); + else + sim_debug(DEBUG_INST, &cpu_dev, "BU%.8x %.8x %.8x ", OPSD1, PSD2, OIR); + } else { + if (MODES & MAPMODE) + sim_debug(DEBUG_INST, &cpu_dev, "NM%.8x %.8x %.8x ", OPSD1, PSD2, OIR); + else + sim_debug(DEBUG_INST, &cpu_dev, "NU%.8x %.8x %.8x ", OPSD1, PSD2, OIR); + } + if (cpu_dev.dctrl & DEBUG_INST) + fprint_inst(sim_deb, OIR, 0); /* display instruction */ + sim_debug(DEBUG_INST, &cpu_dev, + "\n\tR0=%.8x R1=%.8x R2=%.8x R3=%.8x", GPR[0], GPR[1], GPR[2], GPR[3]); + sim_debug(DEBUG_INST, &cpu_dev, + " R4=%.8x R5=%.8x R6=%.8x R7=%.8x\n", GPR[4], GPR[5], GPR[6], GPR[7]); + goto exec; /* go execute the instruction */ + break; + + case 0xAC>>2: /* 0xAC SCC|SD|RM|ADR - SCC|SD|RM|ADR */ /* Lx */ + dest = source; /* set value to load into reg */ + break; + + case 0xB0>>2: /* 0xB0 SCC|SD|RM|ADR - SCC|SD|RM|ADR */ /* LMx */ + /* LMD needs both regs to be masked with R4 */ + if (dbl) { + /* we need to and both regs with R4 */ + t_uint64 nm = (((t_uint64)GPR[4]) << 32) | (((t_uint64)GPR[4]) & D32RMASK); + dest = source & nm; /* mask both regs with reg 4 contents */ + } else { + dest = source; /* <= 32 bits, so just do lower 32 bits */ + dest &= (((t_uint64)GPR[4]) & D32RMASK); /* mask with reg 4 contents */ + if (dest & 0x80000000) /* see if we need to sign extend */ + dest |= D32LMASK; /* force upper word to all ones */ + } + break; + + case 0xB4>>2: /* 0xB4 SCC|SD|RM|ADR - SCC|SD|RM|ADR */ /* LNx */ + dest = NEGATE32(source); /* set the value to load into reg */ + td = dest; + if (dest != 0 && (dest == source || dest == 0x80000000)) + ovr = 1; /* set arithmetic exception status */ + if (FC != 2) { /* do not sign extend DW */ + if (dest & 0x80000000) /* see if we need to sign extend */ + dest |= D32LMASK; /* force upper word to all ones */ + } + /* the arithmetic exception will be handled */ + /* after instruction is completed */ + /* check for arithmetic exception trap enabled */ + if (dest != 0 && ovr && (MODES & AEXPBIT)) { + TRAPME = AEXPCEPT_TRAP; /* set the trap type */ + } + break; + + case 0xBC>>2: /* 0xBC SD|RR|RM|ADR - SD|RR|RM|ADR */ /* SUMx */ + source = NEGATE32(source); + /* Fall through */ + + case 0xB8>>2: /* 0xB8 SD|RR|RM|ADR - SD|RR|RM|ADR */ /* ADMx */ + ovr = 0; + CC = 0; + /* DIAG fixs */ + if (dbl == 0) { + source &= D32RMASK; /* just 32 bits */ + dest &= D32RMASK; /* just 32 bits */ + t = (source & MSIGN) != 0; + t |= ((dest & MSIGN) != 0) ? 2 : 0; + td = dest + source; /* DO ADMx*/ + td &= D32RMASK; /* mask out right most 32 bits */ + dest = 0; /* make place for 64 bits */ + dest |= td; /* insert 32 bit result into dest */ + /* if both signs are neg and result sign is positive, overflow */ + /* if both signs are pos and result sign is negative, overflow */ + if (((t == 3) && ((dest & MSIGN) == 0)) || + ((t == 0) && ((dest & MSIGN) != 0))) + ovr = 1; + if ((td == 0) && ((source & MSIGN) == MSIGN) && ovr) + ovr = 0; /* Diags want 0 and no ovr on MSIGN - MSIGN */ + if (dest & MSIGN) + dest = (D32LMASK | dest); /* sign extend */ + else + dest = (D32RMASK & dest); /* zero fill */ + if (td == 0) + CC |= CC4BIT; /* word is zero, so CC4 */ + else + if (td & 0x80000000) + CC |= CC3BIT; /* it is neg wd, so CC3 */ + else + CC |= CC2BIT; /* then td > 0, so CC2 */ + } else { + /* ADMD */ + t = (source & DMSIGN) != 0; + t |= ((dest & DMSIGN) != 0) ? 2 : 0; + td = dest + source; /* get sum */ + dest = td; /* insert 64 bit result into dest */ + /* if both signs are neg and result sign is positive, overflow */ + /* if both signs are pos and result sign is negative, overflow */ + if (((t == 3) && ((dest & DMSIGN) == 0)) || + ((t == 0) && ((dest & DMSIGN) != 0))) + ovr = 1; + if (td == 0) + CC |= CC4BIT; /* word is zero, so CC4 */ + else + if (td & DMSIGN) + CC |= CC3BIT; /* it is neg wd, so CC3 */ + else + CC |= CC2BIT; /* then td > 0, so CC2 */ + } + if (ovr) + CC |= CC1BIT; /* set overflow CC */ + PSD1 &= 0x87FFFFFE; /* clear the old CC's from PSD1 */ + PSD1 |= CC; /* update the CC's in the PSD */ + + /* the arithmetic exception will be handled */ + /* after instruction is completed */ + /* check for arithmetic exception trap enabled */ + if (ovr && (MODES & AEXPBIT)) { + TRAPME = AEXPCEPT_TRAP; /* set the trap type */ + } + break; + + case 0xC0>>2: /* 0xC0 SCC|SD|RM|ADR - SCC|SD|RM|ADR */ /* MPMx */ + if (reg & 1) { /* see if odd reg specified */ + TRAPME = ADDRSPEC_TRAP; /* bad reg address, error */ + goto newpsd; /* go execute the trap now */ + } + if (FC == 2) { /* must not be double word adddress */ + TRAPME = ADDRSPEC_TRAP; /* bad address, error */ + goto newpsd; /* go execute the trap now */ + } + td = dest; + dest = GPR[reg+1]; /* get low order reg value */ + if (dest & MSIGN) + dest = (D32LMASK | dest); /* sign extend */ + dest = (t_uint64)((t_int64)dest * (t_int64)source); + dbl = 1; + break; + + case 0xC4>>2: /* 0xC4 RM|ADR - RM|ADR */ /* DVMx */ + if (reg & 1) { /* see if odd reg specified */ + TRAPME = ADDRSPEC_TRAP; /* bad reg address, error */ + goto newpsd; /* go execute the trap now */ + } + if (FC == 2) { /* must not be double word adddress */ + TRAPME = ADDRSPEC_TRAP; /* bad address, error */ + goto newpsd; /* go execute the trap now */ + } + if (source == 0) + goto doovr; /* we have div by zero */ + dest = (((t_uint64)GPR[reg]) << 32); /* insert upper reg value */ + dest |= (t_uint64)GPR[reg+1]; /* get low order reg value */ + td = ((t_int64)dest % (t_int64)source); /* remainder */ + if (((td & DMSIGN) ^ (dest & DMSIGN)) != 0) /* Fix sign if needed */ + td = NEGATE32(td); /* dividend and remainder must be same sign */ + dest = (t_int64)dest / (t_int64)source; /* now do the divide */ + int64a = dest; + if (int64a < 0) + int64a = -int64a; + if (int64a > 0x7fffffff) /* if more than 31 bits, we have an error */ + goto doovr; + if (((dest & D32LMASK) != 0 && (dest & D32LMASK) != D32LMASK) || + (((dest & D32LMASK) == D32LMASK) && ((dest & D32RMASK) == 0))) { /* test for overflow */ +doovr: + dest = (((t_uint64)GPR[reg]) << 32);/* insert upper reg value */ + dest |= (t_uint64)GPR[reg+1]; /* get low order reg value */ + ovr = 1; /* the quotient exceeds 31 bit, overflow */ + /* the original regs must be returned unchanged if aexp */ + CC = CC1BIT; /* set ovr CC bit */ + if (dest == 0) + CC |= CC4BIT; /* dw is zero, so CC4 */ + else + if (dest & DMSIGN) + CC |= CC3BIT; /* it is neg dw, so CC3 */ + else + CC |= CC2BIT; /* then dest > 0, so CC2 */ + PSD1 &= 0x87FFFFFE; /* clear the old CC's from PSD1 */ + PSD1 |= CC; /* update the CC's in the PSD */ + /* the arithmetic exception will be handled */ + /* after instruction is completed */ + /* check for arithmetic exception trap enabled */ + if (MODES & AEXPBIT) + TRAPME = AEXPCEPT_TRAP; /* set the trap type */ + } else { + GPR[reg] = (uint32)(td & FMASK); /* reg gets remainder, reg+1 quotient */ + GPR[reg+1] = (uint32)(dest & FMASK); /* store quotient in reg+1 */ + set_CCs(GPR[reg+1], ovr); /* set the CC's, CC1 = ovr */ + } + break; + + case 0xC8>>2: /* 0xC8 IMM - IMM */ /* Immedate */ + temp = GPR[reg]; /* get reg contents */ + addr = IR & RMASK; /* sign extend 16 bit imm value from IR */ + if (addr & 0x8000) /* negative */ + addr |= LMASK; /* extend sign */ + + switch(opr & 0xF) { /* switch on aug code */ + case 0x0: /* LI */ /* SCC | SD */ + GPR[reg] = addr; /* put immediate value into reg */ + set_CCs(addr, ovr); /* set the CC's, CC1 = ovr */ + break; + + case 0x2: /* SUI */ + addr = NEGATE32(addr); /* just make value a negative add */ + /* drop through */ + case 0x1: /* ADI */ + t = (temp & FSIGN) != 0; /* set flag for sign bit not set in reg value */ + t |= ((addr & FSIGN) != 0) ? 2 : 0; /* ditto for the extended immediate value */ + temp = temp + addr; /* now add the numbers */ + /* if both signs are neg and result sign is positive, overflow */ + /* if both signs are pos and result sign is negative, overflow */ + if ((t == 3 && (temp & FSIGN) == 0) || + (t == 0 && (temp & FSIGN) != 0)) + ovr = 1; /* we have an overflow */ + GPR[reg] = temp; /* save the result */ + set_CCs(temp, ovr); /* set the CC's, CC1 = ovr */ + /* the arithmetic exception will be handled */ + /* after instruction is completed */ + /* check for arithmetic exception trap enabled */ + if (ovr && (MODES & AEXPBIT)) { + TRAPME = AEXPCEPT_TRAP; /* set the trap type */ + goto newpsd; /* go execute the trap now */ } break; - case 0xA4>>2: /* 0xA4 ADR - ADR */ /* TBM */ - if ((FC & 04) == 0) { - /* Fault, byte address not allowed */ - TRAPME = ADDRSPEC_TRAP; /* bad reg address, error */ - goto newpsd; /* go execute the trap now */ - } - if ((TRAPME = Mem_read(addr, &temp))) /* get the word from memory */ - goto newpsd; /* memory read error or map fault */ - - t = (PSD1 & 0x70000000) >> 1; /* get old CC bits 1-3 into CCs 2-4*/ - /* use C bits and bits 6-8 (reg) to generate shift bit count */ - bc = ((FC & 3) << 3) | reg; /* get # bits to shift right */ - bc = BIT0 >> bc; /* make a bit mask of bit number */ - PSD1 &= 0x87FFFFFE; /* clear the old CC's from PSD1 */ - if (temp & bc) /* test the bit in memory */ - t |= CC1BIT; /* set CC1 to the bit value */ - PSD1 |= t; /* update the CC's in the PSD */ - break; - - case 0xA8>>2: /* 0xA8 RM|ADR - RM|ADR */ /* EXM */ - if ((FC & 04) != 0 || FC == 2) { /* can not be byte or doubleword */ - /* Fault */ + case 0x3: /* MPI */ + if (reg & 1) { /* see if odd reg specified */ TRAPME = ADDRSPEC_TRAP; /* bad reg address, error */ goto newpsd; /* go execute the trap now */ } - if ((TRAPME = Mem_read(addr, &temp))) { /* get the word from memory */ - if (CPU_MODEL == MODEL_V9) /* V9 wants bit0 set in pfault */ - if (TRAPME == DMDPG) /* demand page request */ - pfault |= 0x80000000; /* set instruction fetch paging error */ - goto newpsd; /* memory read error or map fault */ + /* change immediate value into a 64 bit value */ + source = ((t_uint64)(addr & FMASK)) | ((addr & FSIGN) ? D32LMASK : 0); + temp = GPR[reg+1]; /* get reg multiplier */ + dest = ((t_uint64)(temp & FMASK)) | ((temp & FSIGN) ? D32LMASK : 0); + dest = dest * source; /* do the multiply */ + i_flags |= (SD|SCC); /* save regs and set CC's */ + dbl = 1; /* double reg save */ + break; + + case 0x4: /* DVI */ + if (reg & 1) { /* see if odd reg specified */ + TRAPME = ADDRSPEC_TRAP; /* bad reg address, error */ + goto newpsd; /* go execute the trap now */ + } + /* change immediate value into a 64 bit value */ + source = ((t_uint64)(addr & FMASK)) | ((addr & FSIGN) ? D32LMASK : 0); + if (source == 0) { + goto doovr2; + } + dest = (((t_uint64)GPR[reg]) << 32); /* get upper reg value */ + dest |= (t_uint64)GPR[reg+1]; /* insert low order reg value */ + td = ((t_int64)dest % (t_int64)source); /* remainder */ + /* fix double reg if neg remainder */ + if (((td & DMSIGN) ^ (dest & DMSIGN)) != 0) /* Fix sign if needed */ + td = NEGATE32(td); /* dividend and remainder must be same sign */ + dest = (t_int64)dest / (t_int64)source; /* now do the divide */ + int64a = dest; + if (int64a < 0) + int64a = -int64a; + if (int64a > 0x7fffffff) /* if more than 31 bits, we have an error */ + goto doovr2; + if ((dest & D32LMASK) != 0 && (dest & D32LMASK) != D32LMASK) { /* test for overflow */ +doovr2: + dest = (((t_uint64)GPR[reg]) << 32); /* get upper reg value */ + dest |= (t_uint64)GPR[reg+1]; /* insert low order reg value */ + ovr = 1; /* the quotient exceeds 31 bit, overflow */ + /* the arithmetic exception will be handled */ + /* after instruction is completed */ + /* check for arithmetic exception trap enabled */ + if (MODES & AEXPBIT) + TRAPME = AEXPCEPT_TRAP; /* set the trap type */ + /* the original regs must be returned unchanged if aexp */ + /* put reg values back in dest for CC test */ + CC = CC1BIT; /* set ovr CC bit */ + if (dest == 0) + CC |= CC4BIT; /* dw is zero, so CC4 */ + else + if (dest & DMSIGN) + CC |= CC3BIT; /* it is neg dw, so CC3 */ + else + CC |= CC2BIT; /* then dest > 0, so CC2 */ + PSD1 &= 0x87FFFFFE; /* clear the old CC's from PSD1 */ + PSD1 |= CC; /* update the CC's in the PSD */ + } else { + GPR[reg] = (uint32)(td & FMASK); /* reg gets remainder, reg+1 quotient */ + GPR[reg+1] = (uint32)(dest & FMASK); /* store quotient in reg+1 */ + set_CCs(GPR[reg+1], ovr); /* set the CC's, CC1 = ovr */ + } + break; + + case 0x5: /* CI */ /* SCC */ + temp = ((int)temp - (int)addr); /* subtract imm value from reg value */ + set_CCs(temp, ovr); /* set the CC's, CC1 = ovr */ + break; + +/* SVC instruction format C806 */ +/* |-------+-------+-------+-------+-------+-------+-------+-------| */ +/* |0 0 0 0 0 0|0 0 0|0 1 1|1 1 1 1|1 1 1 1|2 2 2 2 2 2 2 2 2 2 3 3| */ +/* |0 1 2 3 4 5|6 7 8|8 0 1|2 3 4 5|6 7 8 9|0 1 2 3 4 5 6 7 8 9 0 1| */ +/* | Op Code | N/U | N/U | Aug |SVC num| SVC Call Number | */ +/* |1 1 0 0 1 0|0 0 0|0 0 0|0 1 1 0|x x x x|x x x x x x x x x x x x| */ +/* |-------+-------+-------+-------+-------+-------+-------+-------| */ +/* */ + case 0x6: /* SVC none - none */ /* Supervisor Call Trap */ + { +#ifdef MPXTEST /* set to 1 for traceme to work */ + /* get current MPX task name */ + int j; + char n[9]; + uint32 dqe = M[0x8e8>>2]; /* get DQE of current task */ + for (j=0; j<8; j++) { /* get the task name */ + n[j] = (M[((dqe+0x18)>>2)+(j/4)] >> ((3-(j&7))*8)) & 0xff; + if (n[j] == 0) + n[j] = 0x20; + } + n[8] = 0; +#endif + int32c = CPUSTATUS; /* keep for retain blocking state */ + addr = SPAD[0xf0]; /* get trap table memory address from SPAD (def 80) */ + int32a = addr; + if (addr == 0 || addr == 0xffffffff) { /* see if secondary vector table set up */ + TRAPME = ADDRSPEC_TRAP; /* Not setup, error */ + goto newpsd; /* program error */ + } + addr = addr + (0x06 << 2); /* addr has mem addr of SVC trap vector (def 98) */ + temp = M[addr >> 2]; /* get the secondary trap table address from memory */ + if (temp == 0 || temp == 0xffffffff) { /* see if ICB set up */ + TRAPME = ADDRSPEC_TRAP; /* Not setup, error */ + goto newpsd; /* program error */ + } + temp2 = ((IR>>12) & 0x0f) << 2; /* get SVC index from IR */ + t = M[(temp+temp2)>>2]; /* get secondary trap vector address ICB address */ + if (t == 0 || t == 0xffffffff) { /* see if ICB set up */ + TRAPME = ADDRSPEC_TRAP; /* Not setup, error */ + goto newpsd; /* program error */ + } + bc = PSD2 & 0x3ff8; /* get copy of cpix */ + M[t>>2] = (PSD1+4) & 0xfffffffe; /* store PSD 1 + 1W to point to next instruction */ + M[(t>>2)+1] = PSD2; /* store PSD 2 */ + PSD1 = M[(t>>2)+2]; /* get new PSD 1 */ + PSD2 = (M[(t>>2)+3] & ~0x3fff) | bc; /* get new PSD 2 w/old cpix */ + M[(t>>2)+4] = IR&0xFFF; /* store call number */ +#ifdef MPXTEST /* set to 1 for traceme to work */ + sim_debug(DEBUG_IRQ, &cpu_dev, + "SVC %x,%x @ %.8x PSD %.8x %.8x SPAD PSD2 %x C.CURR %x LMN %8s\n", + temp2>>2, IR&0xFFF, OPSD1, PSD1, PSD2, SPAD[0xf5], dqe, n); + sim_debug(DEBUG_IRQ, &cpu_dev, + "R0=%.8x R1=%.8x R2=%.8x R3=%.8x\n", GPR[0], GPR[1], GPR[2], GPR[3]); + sim_debug(DEBUG_IRQ, &cpu_dev, + "R4=%.8x R5=%.8x R6=%.8x R7=%.8x\n", GPR[4], GPR[5], GPR[6], GPR[7]); +#endif + /* set the mode bits and CCs from the new PSD */ + CC = PSD1 & 0x78000000; /* extract bits 1-4 from PSD1 */ + MODES = PSD1 & 0x87000000; /* extract bits 0, 5, 6, 7 from PSD 1 */ + CPUSTATUS &= ~0x87000000; /* reset bits in CPUSTATUS */ + CPUSTATUS |= MODES; /* now insert into CPUSTATUS */ + + /* set new map mode and interrupt blocking state in CPUSTATUS */ + if (PSD2 & MAPBIT) { + CPUSTATUS |= BIT8; /* set bit 8 of cpu status */ + MODES |= MAPMODE; /* set mapped mode */ + } else + CPUSTATUS &= ~BIT8; /* reset bit 8 of cpu status */ + + /* set interrupt blocking state */ + if ((PSD2 & RETBBIT) == 0) { /* is it retain blocking state */ + if (PSD2 & SETBBIT) { /* no, is it set blocking state */ + CPUSTATUS |= BIT24; /* yes, set blk state in cpu status bit 24 */ + MODES |= BLKMODE; /* set blocked mode */ + } else { + CPUSTATUS &= ~BIT24; /* no, reset blk state in cpu status bit 24 */ + MODES &= ~BLKMODE; /* reset blocked mode */ + irq_pend = 1; /* start scanning interrupts again */ +#ifdef LEAVE_ACTIVE + if (irq_auto) { +/*AIR*/ INTS[irq_auto] &= ~INTS_ACT; /* deactivate specified int level */ +/*AIR*/ SPAD[irq_auto+0x80] &= ~SINT_ACT; /* deactivate in SPAD too */ + sim_debug(DEBUG_IRQ, &cpu_dev, + "<|>IntX deactivate level %02x at SVC #%2x PSD1 %08x\n", + irq_auto, temp2, PSD1); +/*AIR*/ irq_auto = 0; /* show done processing in blocked mode */ + skipinstr = 1; /* skip interrupt test */ + } +#endif + } + } else { + /* handle retain blocking state */ + PSD2 &= ~RETMBIT; /* turn off retain bit in PSD2 */ + /* set new blocking state in PSD2 */ + PSD2 &= ~(SETBBIT|RETBBIT); /* clear bit 48 & 49 to be unblocked */ + MODES &= ~(BLKMODE|RETMODE); /* reset blocked & retain mode bits */ + if (int32c & BIT24) { /* see if old mode is blocked */ + PSD2 |= SETBBIT; /* set to blocked state */ + MODES |= BLKMODE; /* set blocked mode */ + } } - IR = temp; /* get instruction from memory */ - if (FC == 3) /* see if right halfword specified */ - IR <<= 16; /* move over the HW instruction */ + SPAD[0xf5] = PSD2; /* save the current PSD2 */ + SPAD[0xf9] = CPUSTATUS; /* save the cpu status in SPAD */ + TRAPME = 0; /* not to be processed as trap */ + goto newpsd; /* new psd loaded */ + } + break; + + case 0x7: /* EXR */ + IR = temp; /* get instruction to execute */ + /* if bit 30 set, instruction is in right hw, do EXRR */ + if (addr & 2) + IR <<= 16; /* move instruction to left HW */ #ifdef DIAG_SAYS_OK_TO_EXECUTE_ANOTHER_EXECUTE - if ((IR & 0xFC7F0000) == 0xC8070000 || /* No EXR target */ - (IR & 0xFF800000) == 0xA8000000 || /* No EXM target */ - (IR & 0xFC000000) == 0x80000000) { -#else /* 32/67 diag says execute of execute is OK */ - if ((IR & 0xFC000000) == 0x80000000) { -#endif - /* Fault, attempt to execute another EXR, EXRR, EXM, or LEAR */ + if ((IR & 0xFC7F0000) == 0xC8070000 || + (IR & 0xFF800000) == 0xA8000000) { + /* Fault, attempt to execute another EXR, EXRR, or EXM */ goto inv; /* invalid instruction */ } - EXM_EXR = 4; /* set PC increment for EXM */ - - OPSD1 &= 0x87FFFFFE; /* clear the old PSD CC's */ - OPSD1 |= PSD1 & 0x78000000; /* update the CC's in the old PSD */ +#endif + EXM_EXR = 4; /* set PC increment for EXR */ + OPSD1 &= 0x87FFFFFE; /* clear the old CC's */ + OPSD1 |= PSD1 & 0x78000000; /* update the CC's in the PSD */ /* TODO Update other history information for this instruction */ if (hst_lnt) { hst[hst_p].opsd1 = OPSD1; /* update the CC in opsd1 */ @@ -5057,21 +5479,20 @@ meoa: /* merge point for eor, and, or */ hst[hst_p].reg[ix+8] = BR[ix]; /* save breg */ } } - /* DEBUG_INST support code */ OPSD1 &= 0x87FFFFFE; /* clear the old CC's */ OPSD1 |= PSD1 & 0x78000000; /* update the CC's in the PSD */ /* output mapped/unmapped */ if (MODES & BASEBIT) { - if (MODES & MAPMODE) - sim_debug(DEBUG_INST, &cpu_dev, "BM%.8x %.8x %.8x ", OPSD1, PSD2, OIR); - else - sim_debug(DEBUG_INST, &cpu_dev, "BU%.8x %.8x %.8x ", OPSD1, PSD2, OIR); + if (MODES & MAPMODE) + sim_debug(DEBUG_INST, &cpu_dev, "BM%.8x %.8x %.8x ", OPSD1, PSD2, OIR); + else + sim_debug(DEBUG_INST, &cpu_dev, "BU%.8x %.8x %.8x ", OPSD1, PSD2, OIR); } else { - if (MODES & MAPMODE) - sim_debug(DEBUG_INST, &cpu_dev, "NM%.8x %.8x %.8x ", OPSD1, PSD2, OIR); - else - sim_debug(DEBUG_INST, &cpu_dev, "NU%.8x %.8x %.8x ", OPSD1, PSD2, OIR); + if (MODES & MAPMODE) + sim_debug(DEBUG_INST, &cpu_dev, "NM%.8x %.8x %.8x ", OPSD1, PSD2, OIR); + else + sim_debug(DEBUG_INST, &cpu_dev, "NU%.8x %.8x %.8x ", OPSD1, PSD2, OIR); } if (cpu_dev.dctrl & DEBUG_INST) fprint_inst(sim_deb, OIR, 0); /* display instruction */ @@ -5081,600 +5502,145 @@ meoa: /* merge point for eor, and, or */ " R4=%.8x R5=%.8x R6=%.8x R7=%.8x\n", GPR[4], GPR[5], GPR[6], GPR[7]); goto exec; /* go execute the instruction */ break; - - case 0xAC>>2: /* 0xAC SCC|SD|RM|ADR - SCC|SD|RM|ADR */ /* Lx */ - dest = source; /* set value to load into reg */ + + /* these instruction were never used by MPX, only diags */ + /* diags treat them as invalid halfword instructions */ + /* so set the HLF flag to get proper PC increment */ + case 0x8: /* SEM */ + case 0x9: /* LEM */ + case 0xA: /* CEMA */ + case 0xB: /* INV */ + case 0xC: /* INV */ + case 0xD: /* INV */ + case 0xE: /* INV */ + case 0xF: /* INV */ + default: + goto inv; /* invalid instruction */ break; + } + break; - case 0xB0>>2: /* 0xB0 SCC|SD|RM|ADR - SCC|SD|RM|ADR */ /* LMx */ - /* LMD needs both regs to be masked with R4 */ - if (dbl) { - /* we need to and both regs with R4 */ - t_uint64 nm = (((t_uint64)GPR[4]) << 32) | (((t_uint64)GPR[4]) & D32RMASK); - dest = source & nm; /* mask both regs with reg 4 contents */ - } else { - dest = source; /* <= 32 bits, so just do lower 32 bits */ - dest &= (((t_uint64)GPR[4]) & D32RMASK); /* mask with reg 4 contents */ - if (dest & 0x80000000) /* see if we need to sign extend */ - dest |= D32LMASK; /* force upper word to all ones */ - } - break; - - case 0xB4>>2: /* 0xB4 SCC|SD|RM|ADR - SCC|SD|RM|ADR */ /* LNx */ - dest = NEGATE32(source); /* set the value to load into reg */ - td = dest; - if (dest != 0 && (dest == source || dest == 0x80000000)) - ovr = 1; /* set arithmetic exception status */ - if (FC != 2) /* do not sign extend DW */ - if (dest & 0x80000000) /* see if we need to sign extend */ - dest |= D32LMASK; /* force upper word to all ones */ - /* the arithmetic exception will be handled */ - /* after instruction is completed */ - /* check for arithmetic exception trap enabled */ - if (dest != 0 && ovr && (MODES & AEXPBIT)) { - TRAPME = AEXPCEPT_TRAP; /* set the trap type */ + case 0xCC>>2: /* 0xCC ADR - ADR */ /* LF */ + /* For machines with Base mode 0xCC08 stores base registers */ + if ((FC & 3) != 0) { /* must be word address */ + TRAPME = ADDRSPEC_TRAP; /* bad reg address, error */ + goto newpsd; /* go execute the trap now */ + } + temp = addr & 0xffe000; /* get 11 bit map # */ + bc = addr & 0x20; /* bit 26 initial value */ + while (reg < 8) { + if (bc != (addr & 0x20)) { /* test for crossing file boundry */ + if (CPU_MODEL < MODEL_27) { + TRAPME = ADDRSPEC_TRAP; /* bad reg address, error */ + goto newpsd; /* go execute the trap now */ + } } - break; - - case 0xBC>>2: /* 0xBC SD|RR|RM|ADR - SD|RR|RM|ADR */ /* SUMx */ - source = NEGATE32(source); - /* Fall through */ - - case 0xB8>>2: /* 0xB8 SD|RR|RM|ADR - SD|RR|RM|ADR */ /* ADMx */ - ovr = 0; - CC = 0; - /* DIAG fixs */ - if (dbl == 0) { - source &= D32RMASK; /* just 32 bits */ - dest &= D32RMASK; /* just 32 bits */ - t = (source & MSIGN) != 0; - t |= ((dest & MSIGN) != 0) ? 2 : 0; - td = dest + source; /* DO ADMx*/ - td &= D32RMASK; /* mask out right most 32 bits */ - dest = 0; /* make place for 64 bits */ - dest |= td; /* insert 32 bit result into dest */ - /* if both signs are neg and result sign is positive, overflow */ - /* if both signs are pos and result sign is negative, overflow */ - if (((t == 3) && ((dest & MSIGN) == 0)) || - ((t == 0) && ((dest & MSIGN) != 0))) - ovr = 1; - if ((td == 0) && ((source & MSIGN) == MSIGN) && ovr) - ovr = 0; /* Diags want 0 and no ovr on MSIGN - MSIGN */ - if (dest & MSIGN) - dest = (D32LMASK | dest); /* sign extend */ - else - dest = (D32RMASK & dest); /* zero fill */ - if (td == 0) - CC |= CC4BIT; /* word is zero, so CC4 */ - else - if (td & 0x80000000) - CC |= CC3BIT; /* it is neg wd, so CC3 */ - else - CC |= CC2BIT; /* then td > 0, so CC2 */ - } else { - /* ADMD */ - t = (source & DMSIGN) != 0; - t |= ((dest & DMSIGN) != 0) ? 2 : 0; - td = dest + source; /* get sum */ - dest = td; /* insert 64 bit result into dest */ - /* if both signs are neg and result sign is positive, overflow */ - /* if both signs are pos and result sign is negative, overflow */ - if (((t == 3) && ((dest & DMSIGN) == 0)) || - ((t == 0) && ((dest & DMSIGN) != 0))) - ovr = 1; - if (td == 0) - CC |= CC4BIT; /* word is zero, so CC4 */ - else - if (td & DMSIGN) - CC |= CC3BIT; /* it is neg wd, so CC3 */ - else - CC |= CC2BIT; /* then td > 0, so CC2 */ + if (temp != (addr & 0xffe000)) { /* test for crossing map boundry */ + if (CPU_MODEL >= MODEL_V6) { + TRAPME = ADDRSPEC_TRAP; /* bad reg address, error */ + goto newpsd; /* go execute the trap now */ + } } - if (ovr) - CC |= CC1BIT; /* set overflow CC */ - PSD1 &= 0x87FFFFFE; /* clear the old CC's from PSD1 */ - PSD1 |= CC; /* update the CC's in the PSD */ + if (FC & 0x4) /* LFBR? 0xCC08 */ + TRAPME = Mem_read(addr, &BR[reg]); /* read the base reg */ + else /* LF? 0xCC00 */ + TRAPME = Mem_read(addr, &GPR[reg]); /* read the GPR reg */ + if (TRAPME) /* TRAPME has error */ + goto newpsd; /* go execute the trap now */ + reg++; /* next reg to write */ + addr += 4; /* next addr */ + } + break; - /* the arithmetic exception will be handled */ - /* after instruction is completed */ - /* check for arithmetic exception trap enabled */ - if (ovr && (MODES & AEXPBIT)) { - TRAPME = AEXPCEPT_TRAP; /* set the trap type */ + case 0xD0>>2: /* 0xD0 SD|ADR - INV */ /* LEA none basemode only */ + if (MODES & BASEBIT) + goto inv; /* invalid instruction in basemode */ + /* bc has last bits 0,1 for indirect addr of both 1 for no indirection */ + addr &= 0x3fffffff; /* clear bits 0-1 */ + addr |= bc; /* insert bits 0,1 values into address */ + if (FC & 0x4) + addr |= F_BIT; /* copy F bit from instruction */ + dest = (t_uint64)(addr); + break; + + case 0xD4>>2: /* 0xD4 RR|SM|ADR - RR|SM|ADR */ /* STx */ + break; + + case 0xD8>>2: /* 0xD8 RR|SM|ADR - RR|SM|ADR */ /* STMx */ + /* STMD needs both regs to be masked with R4 */ + if (dbl) { + /* we need to and both regs */ + t_uint64 nm = (((t_uint64)GPR[4]) << 32) | (((t_uint64)GPR[4]) & D32RMASK); + dest &= nm; /* mask both regs with reg 4 contents */ + } else { + dest &= (((t_uint64)GPR[4]) & D32RMASK); /* mask with reg 4 contents */ + } + break; + + case 0xDC>>2: /* 0xDC INV - ADR */ /* INV nonbasemode (STFx basemode) */ + /* DC00 STF */ /* DC08 STFBR */ + if ((FC & 0x4) && (CPU_MODEL <= MODEL_27)) { + /* basemode undefined for 32/7x & 32/27 */ + TRAPME = UNDEFINSTR_TRAP; /* Undefined Instruction Trap */ + if ((CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9)) + TRAPSTATUS |= BIT0; /* set bit 0 of trap status */ + goto newpsd; /* handle trap */ + } + /* For machines with Base mode 0xDC08 stores base registers */ + if ((FC & 3) != 0) { /* must be word address */ + TRAPME = ADDRSPEC_TRAP; /* bad reg address, error */ + goto newpsd; /* go execute the trap now */ + } + bc = addr & 0x20; /* bit 26 initial value */ + temp = addr & 0xffe000; /* get 11 bit map # */ + while (reg < 8) { + if (bc != (addr & 0x20)) { /* test for crossing file boundry */ + if (CPU_MODEL < MODEL_27) { + TRAPME = ADDRSPEC_TRAP; /* bad reg address, error */ + goto newpsd; /* go execute the trap now */ + } } - break; - - case 0xC0>>2: /* 0xC0 SCC|SD|RM|ADR - SCC|SD|RM|ADR */ /* MPMx */ - if (reg & 1) { /* see if odd reg specified */ - TRAPME = ADDRSPEC_TRAP; /* bad reg address, error */ - goto newpsd; /* go execute the trap now */ + if (temp != (addr & 0xffe000)) { /* test for crossing map boundry */ + if (CPU_MODEL >= MODEL_V6) { + TRAPME = ADDRSPEC_TRAP; /* bad reg address, error */ + goto newpsd; /* go execute the trap now */ + } } - if (FC == 2) { /* must not be double word adddress */ - TRAPME = ADDRSPEC_TRAP; /* bad address, error */ - goto newpsd; /* go execute the trap now */ - } - td = dest; - dest = GPR[reg+1]; /* get low order reg value */ - if (dest & MSIGN) - dest = (D32LMASK | dest); /* sign extend */ - dest = (t_uint64)((t_int64)dest * (t_int64)source); - dbl = 1; - break; + if (FC & 0x4) /* STFBR? */ + TRAPME = Mem_write(addr, &BR[reg]); /* store the base reg */ + else /* STF */ + TRAPME = Mem_write(addr, &GPR[reg]); /* store the GPR reg */ + if (TRAPME) /* TRAPME has error */ + goto newpsd; /* go execute the trap now */ + reg++; /* next reg to write */ + addr += 4; /* next addr */ + } + break; - case 0xC4>>2: /* 0xC4 RM|ADR - RM|ADR */ /* DVMx */ - if (reg & 1) { /* see if odd reg specified */ - TRAPME = ADDRSPEC_TRAP; /* bad reg address, error */ - goto newpsd; /* go execute the trap now */ - } - if (FC == 2) { /* must not be double word adddress */ - TRAPME = ADDRSPEC_TRAP; /* bad address, error */ - goto newpsd; /* go execute the trap now */ - } - if (source == 0) - goto doovr; /* we have div by zero */ - dest = (((t_uint64)GPR[reg]) << 32); /* insert upper reg value */ - dest |= (t_uint64)GPR[reg+1]; /* get low order reg value */ - td = ((t_int64)dest % (t_int64)source); /* remainder */ - if (((td & DMSIGN) ^ (dest & DMSIGN)) != 0) /* Fix sign if needed */ - td = NEGATE32(td); /* dividend and remainder must be same sign */ - dest = (t_int64)dest / (t_int64)source; /* now do the divide */ - int64a = dest; - if (int64a < 0) - int64a = -int64a; - if (int64a > 0x7fffffff) /* if more than 31 bits, we have an error */ - goto doovr; - if (((dest & D32LMASK) != 0 && (dest & D32LMASK) != D32LMASK) || - (((dest & D32LMASK) == D32LMASK) && ((dest & D32RMASK) == 0))) { /* test for overflow */ -doovr: - dest = (((t_uint64)GPR[reg]) << 32);/* insert upper reg value */ - dest |= (t_uint64)GPR[reg+1]; /* get low order reg value */ - ovr = 1; /* the quotient exceeds 31 bit, overflow */ - /* the original regs must be returned unchanged if aexp */ - CC = CC1BIT; /* set ovr CC bit */ - if (dest == 0) - CC |= CC4BIT; /* dw is zero, so CC4 */ - else - if (dest & DMSIGN) - CC |= CC3BIT; /* it is neg dw, so CC3 */ - else - CC |= CC2BIT; /* then dest > 0, so CC2 */ - PSD1 &= 0x87FFFFFE; /* clear the old CC's from PSD1 */ - PSD1 |= CC; /* update the CC's in the PSD */ - /* the arithmetic exception will be handled */ - /* after instruction is completed */ - /* check for arithmetic exception trap enabled */ - if (MODES & AEXPBIT) - TRAPME = AEXPCEPT_TRAP; /* set the trap type */ - } else { - GPR[reg] = (uint32)(td & FMASK); /* reg gets remainder, reg+1 quotient */ - GPR[reg+1] = (uint32)(dest & FMASK); /* store quotient in reg+1 */ - set_CCs(GPR[reg+1], ovr); /* set the CC's, CC1 = ovr */ - } - break; - - case 0xC8>>2: /* 0xC8 IMM - IMM */ /* Immedate */ - temp = GPR[reg]; /* get reg contents */ - addr = IR & RMASK; /* sign extend 16 bit imm value from IR */ - if (addr & 0x8000) /* negative */ - addr |= LMASK; /* extend sign */ - - switch(opr & 0xF) { /* switch on aug code */ - case 0x0: /* LI */ /* SCC | SD */ - GPR[reg] = addr; /* put immediate value into reg */ - set_CCs(addr, ovr); /* set the CC's, CC1 = ovr */ - break; - - case 0x2: /* SUI */ - addr = NEGATE32(addr); /* just make value a negative add */ - /* drop through */ - case 0x1: /* ADI */ - t = (temp & FSIGN) != 0; /* set flag for sign bit not set in reg value */ - t |= ((addr & FSIGN) != 0) ? 2 : 0; /* ditto for the extended immediate value */ - temp = temp + addr; /* now add the numbers */ - /* if both signs are neg and result sign is positive, overflow */ - /* if both signs are pos and result sign is negative, overflow */ - if ((t == 3 && (temp & FSIGN) == 0) || - (t == 0 && (temp & FSIGN) != 0)) - ovr = 1; /* we have an overflow */ - GPR[reg] = temp; /* save the result */ - set_CCs(temp, ovr); /* set the CC's, CC1 = ovr */ - /* the arithmetic exception will be handled */ - /* after instruction is completed */ - /* check for arithmetic exception trap enabled */ - if (ovr && (MODES & AEXPBIT)) { - TRAPME = AEXPCEPT_TRAP; /* set the trap type */ - goto newpsd; /* go execute the trap now */ - } - break; - - case 0x3: /* MPI */ - if (reg & 1) { /* see if odd reg specified */ - TRAPME = ADDRSPEC_TRAP; /* bad reg address, error */ - goto newpsd; /* go execute the trap now */ - } - /* change immediate value into a 64 bit value */ - source = ((t_uint64)(addr & FMASK)) | ((addr & FSIGN) ? D32LMASK : 0); - temp = GPR[reg+1]; /* get reg multiplier */ - dest = ((t_uint64)(temp & FMASK)) | ((temp & FSIGN) ? D32LMASK : 0); - dest = dest * source; /* do the multiply */ - i_flags |= (SD|SCC); /* save regs and set CC's */ - dbl = 1; /* double reg save */ - break; - - case 0x4: /* DVI */ - if (reg & 1) { /* see if odd reg specified */ - TRAPME = ADDRSPEC_TRAP; /* bad reg address, error */ - goto newpsd; /* go execute the trap now */ - } - /* change immediate value into a 64 bit value */ - source = ((t_uint64)(addr & FMASK)) | ((addr & FSIGN) ? D32LMASK : 0); - if (source == 0) { - goto doovr2; - } - dest = (((t_uint64)GPR[reg]) << 32); /* get upper reg value */ - dest |= (t_uint64)GPR[reg+1]; /* insert low order reg value */ - td = ((t_int64)dest % (t_int64)source); /* remainder */ - /* fix double reg if neg remainder */ - if (((td & DMSIGN) ^ (dest & DMSIGN)) != 0) /* Fix sign if needed */ - td = NEGATE32(td); /* dividend and remainder must be same sign */ - dest = (t_int64)dest / (t_int64)source; /* now do the divide */ - int64a = dest; - if (int64a < 0) - int64a = -int64a; - if (int64a > 0x7fffffff) /* if more than 31 bits, we have an error */ - goto doovr2; - if ((dest & D32LMASK) != 0 && (dest & D32LMASK) != D32LMASK) { /* test for overflow */ -doovr2: - dest = (((t_uint64)GPR[reg]) << 32); /* get upper reg value */ - dest |= (t_uint64)GPR[reg+1]; /* insert low order reg value */ - ovr = 1; /* the quotient exceeds 31 bit, overflow */ - /* the arithmetic exception will be handled */ - /* after instruction is completed */ - /* check for arithmetic exception trap enabled */ - if (MODES & AEXPBIT) - TRAPME = AEXPCEPT_TRAP; /* set the trap type */ - /* the original regs must be returned unchanged if aexp */ - /* put reg values back in dest for CC test */ - CC = CC1BIT; /* set ovr CC bit */ - if (dest == 0) - CC |= CC4BIT; /* dw is zero, so CC4 */ - else - if (dest & DMSIGN) - CC |= CC3BIT; /* it is neg dw, so CC3 */ - else - CC |= CC2BIT; /* then dest > 0, so CC2 */ - PSD1 &= 0x87FFFFFE; /* clear the old CC's from PSD1 */ - PSD1 |= CC; /* update the CC's in the PSD */ - } else { - GPR[reg] = (uint32)(td & FMASK); /* reg gets remainder, reg+1 quotient */ - GPR[reg+1] = (uint32)(dest & FMASK); /* store quotient in reg+1 */ - set_CCs(GPR[reg+1], ovr); /* set the CC's, CC1 = ovr */ - } - break; - - case 0x5: /* CI */ /* SCC */ - temp = ((int)temp - (int)addr); /* subtract imm value from reg value */ - set_CCs(temp, ovr); /* set the CC's, CC1 = ovr */ - break; - -/* SVC instruction format C806 */ -/* |-------+-------+-------+-------+-------+-------+-------+-------| */ -/* |0 0 0 0 0 0|0 0 0|0 1 1|1 1 1 1|1 1 1 1|2 2 2 2 2 2 2 2 2 2 3 3| */ -/* |0 1 2 3 4 5|6 7 8|8 0 1|2 3 4 5|6 7 8 9|0 1 2 3 4 5 6 7 8 9 0 1| */ -/* | Op Code | N/U | N/U | Aug |SVC num| SVC Call Number | */ -/* |1 1 0 0 1 0|0 0 0|0 0 0|0 1 1 0|x x x x|x x x x x x x x x x x x| */ -/* |-------+-------+-------+-------+-------+-------+-------+-------| */ -/* */ - case 0x6: /* SVC none - none */ /* Supervisor Call Trap */ - { -#ifdef MPXTEST /* set to 1 for traceme to work */ - /* get current MPX task name */ - int j; - char n[9]; - uint32 dqe = M[0x8e8>>2]; /* get DQE of current task */ - for (j=0; j<8; j++) { /* get the task name */ - n[j] = (M[((dqe+0x18)>>2)+(j/4)] >> ((3-(j&7))*8)) & 0xff; - if (n[j] == 0) - n[j] = 0x20; - } - n[8] = 0; -#endif - int32c = CPUSTATUS; /* keep for retain blocking state */ - addr = SPAD[0xf0]; /* get trap table memory address from SPAD (def 80) */ - int32a = addr; - if (addr == 0 || addr == 0xffffffff) { /* see if secondary vector table set up */ - TRAPME = ADDRSPEC_TRAP; /* Not setup, error */ - goto newpsd; /* program error */ - } - addr = addr + (0x06 << 2); /* addr has mem addr of SVC trap vector (def 98) */ - temp = M[addr >> 2]; /* get the secondary trap table address from memory */ - if (temp == 0 || temp == 0xffffffff) { /* see if ICB set up */ - TRAPME = ADDRSPEC_TRAP; /* Not setup, error */ - goto newpsd; /* program error */ - } - temp2 = ((IR>>12) & 0x0f) << 2; /* get SVC index from IR */ - t = M[(temp+temp2)>>2]; /* get secondary trap vector address ICB address */ - if (t == 0 || t == 0xffffffff) { /* see if ICB set up */ - TRAPME = ADDRSPEC_TRAP; /* Not setup, error */ - goto newpsd; /* program error */ - } -#ifdef NOT_NOW -sim_debug(DEBUG_IRQ, &cpu_dev, -"SVC IR %08x #%02x call #%03x TTA %04x SVCTA %06x 2ndTTA %06x\n", -IR, temp2>>2, IR&0xFFF, int32a, temp, t); -#endif - bc = PSD2 & 0x3ff8; /* get copy of cpix */ - M[t>>2] = (PSD1+4) & 0xfffffffe; /* store PSD 1 + 1W to point to next instruction */ - M[(t>>2)+1] = PSD2; /* store PSD 2 */ - PSD1 = M[(t>>2)+2]; /* get new PSD 1 */ -//0120 PSD2 = (M[(t>>2)+3] & ~0x3ff8) | bc; /* get new PSD 2 w/old cpix */ - PSD2 = (M[(t>>2)+3] & ~0x3fff) | bc; /* get new PSD 2 w/old cpix */ - M[(t>>2)+4] = IR&0xFFF; /* store call number */ -#ifdef NOT_NOW -sim_debug(DEBUG_IRQ, &cpu_dev, -"SVC #%02x call #%03x PSD1 %08x PSD2 %08x CPUSTATUS %08x\n", -temp2>>2, IR&0xFFF, PSD1, PSD2, CPUSTATUS); -#endif -#ifdef MPXTEST /* set to 1 for traceme to work */ -sim_debug(DEBUG_IRQ, &cpu_dev, - "SVC %x,%x @ %.8x PSD %.8x %.8x SPAD PSD2 %x C.CURR %x LMN %8s\n", - temp2>>2, IR&0xFFF, OPSD1, PSD1, PSD2, SPAD[0xf5], dqe, n); -sim_debug(DEBUG_IRQ, &cpu_dev, - "R0=%.8x R1=%.8x R2=%.8x R3=%.8x\n", GPR[0], GPR[1], GPR[2], GPR[3]); -sim_debug(DEBUG_IRQ, &cpu_dev, - "R4=%.8x R5=%.8x R6=%.8x R7=%.8x\n", GPR[4], GPR[5], GPR[6], GPR[7]); - -// if (((temp2>>2) == 1) && ((IR&0xfff) == 0x6d) && (n[1] == 'B')) { - if (((temp2>>2) == 1) && ((IR&0xfff) == 0x6b) && (n[1] == 'B')) { -//210 cpu_dev.dctrl |= DEBUG_INST; /* start instruction trace */ - } - if (((temp2>>2) == 1) && ((IR&0xfff) == 0x7c) && (n[1] == 'B')) { -//sim_debug(DEBUG_IRQ, &cpu_dev, -// "SVC %x,%x GPR[6] %x GPR[6] %x\n", temp2>>2, IR&0xfff, GPR[6], GPR[7]); -//210 cpu_dev.dctrl |= DEBUG_INST; /* start instruction trace */ - } -#endif - /* set the mode bits and CCs from the new PSD */ - CC = PSD1 & 0x78000000; /* extract bits 1-4 from PSD1 */ - MODES = PSD1 & 0x87000000; /* extract bits 0, 5, 6, 7 from PSD 1 */ - CPUSTATUS &= ~0x87000000; /* reset bits in CPUSTATUS */ - CPUSTATUS |= MODES; /* now insert into CPUSTATUS */ - - /* set new map mode and interrupt blocking state in CPUSTATUS */ - if (PSD2 & MAPBIT) { - CPUSTATUS |= BIT8; /* set bit 8 of cpu status */ - MODES |= MAPMODE; /* set mapped mode */ - } else - CPUSTATUS &= ~BIT8; /* reset bit 8 of cpu status */ - - /* set interrupt blocking state */ - if ((PSD2 & RETBBIT) == 0) { /* is it retain blocking state */ - if (PSD2 & SETBBIT) { /* no, is it set blocking state */ - CPUSTATUS |= BIT24; /* yes, set blk state in cpu status bit 24 */ - MODES |= BLKMODE; /* set blocked mode */ - } else { - CPUSTATUS &= ~BIT24; /* no, reset blk state in cpu status bit 24 */ - MODES &= ~BLKMODE; /* reset blocked mode */ - irq_pend = 1; /* start scanning interrupts again */ -#ifdef LEAVE_ACTIVE - if (irq_auto) { -/*AIR*/ INTS[irq_auto] &= ~INTS_ACT; /* deactivate specified int level */ -/*AIR*/ SPAD[irq_auto+0x80] &= ~SINT_ACT; /* deactivate in SPAD too */ - sim_debug(DEBUG_IRQ, &cpu_dev, - "<|>IntX deactivate level %02x at SVC #%2x PSD1 %08x\n", - irq_auto, temp2, PSD1); -/*AIR*/ irq_auto = 0; /* show done processing in blocked mode */ -/*103020*/ skipinstr = 1; /* skip interrupt test */ - } -#endif - } - } else { - /* handle retain blocking state */ - PSD2 &= ~RETMBIT; /* turn off retain bit in PSD2 */ - /* set new blocking state in PSD2 */ - PSD2 &= ~(SETBBIT|RETBBIT); /* clear bit 48 & 49 to be unblocked */ - MODES &= ~(BLKMODE|RETMODE);/* reset blocked & retain mode bits */ - if (int32c & BIT24) { /* see if old mode is blocked */ - PSD2 |= SETBBIT; /* set to blocked state */ - MODES |= BLKMODE; /* set blocked mode */ - } - } - - SPAD[0xf5] = PSD2; /* save the current PSD2 */ - SPAD[0xf9] = CPUSTATUS; /* save the cpu status in SPAD */ - TRAPME = 0; /* not to be processed as trap */ - goto newpsd; /* new psd loaded */ - } - break; - - case 0x7: /* EXR */ - IR = temp; /* get instruction to execute */ - /* if bit 30 set, instruction is in right hw, do EXRR */ - if (addr & 2) - IR <<= 16; /* move instruction to left HW */ -#ifdef DIAG_SAYS_OK_TO_EXECUTE_ANOTHER_EXECUTE - /* 32/67 diag says execute of execute is OK */ - if ((IR & 0xFC7F0000) == 0xC8070000 || - (IR & 0xFF800000) == 0xA8000000) { - /* Fault, attempt to execute another EXR, EXRR, or EXM */ - goto inv; /* invalid instruction */ - } -#endif - EXM_EXR = 4; /* set PC increment for EXR */ - OPSD1 &= 0x87FFFFFE; /* clear the old CC's */ - OPSD1 |= PSD1 & 0x78000000; /* update the CC's in the PSD */ - /* TODO Update other history information for this instruction */ - if (hst_lnt) { - hst[hst_p].opsd1 = OPSD1; /* update the CC in opsd1 */ - hst[hst_p].npsd1 = PSD1; /* save new psd1 */ - hst[hst_p].npsd2 = PSD2; /* save new psd2 */ - hst[hst_p].modes = MODES; /* save current mode bits */ - for (ix=0; ix<8; ix++) { - hst[hst_p].reg[ix] = GPR[ix]; /* save reg */ - hst[hst_p].reg[ix+8] = BR[ix]; /* save breg */ - } - } - /* DEBUG_INST support code */ - OPSD1 &= 0x87FFFFFE; /* clear the old CC's */ - OPSD1 |= PSD1 & 0x78000000; /* update the CC's in the PSD */ - /* output mapped/unmapped */ - if (MODES & BASEBIT) { - if (MODES & MAPMODE) - sim_debug(DEBUG_INST, &cpu_dev, "BM%.8x %.8x %.8x ", OPSD1, PSD2, OIR); - else - sim_debug(DEBUG_INST, &cpu_dev, "BU%.8x %.8x %.8x ", OPSD1, PSD2, OIR); - } else { - if (MODES & MAPMODE) - sim_debug(DEBUG_INST, &cpu_dev, "NM%.8x %.8x %.8x ", OPSD1, PSD2, OIR); - else - sim_debug(DEBUG_INST, &cpu_dev, "NU%.8x %.8x %.8x ", OPSD1, PSD2, OIR); - } - if (cpu_dev.dctrl & DEBUG_INST) - fprint_inst(sim_deb, OIR, 0); /* display instruction */ - sim_debug(DEBUG_INST, &cpu_dev, - "\n\tR0=%.8x R1=%.8x R2=%.8x R3=%.8x", GPR[0], GPR[1], GPR[2], GPR[3]); - sim_debug(DEBUG_INST, &cpu_dev, - " R4=%.8x R5=%.8x R6=%.8x R7=%.8x\n", GPR[4], GPR[5], GPR[6], GPR[7]); - goto exec; /* go execute the instruction */ - break; - - /* these instruction were never used by MPX, only diags */ - /* diags treat them as invalid halfword instructions */ - /* so set the HLF flag to get proper PC increment */ - case 0x8: /* SEM */ - case 0x9: /* LEM */ - case 0xA: /* CEMA */ - case 0xB: /* INV */ - case 0xC: /* INV */ - case 0xD: /* INV */ - case 0xE: /* INV */ - case 0xF: /* INV */ - default: - goto inv; /* invalid instruction */ - break; - } - break; - - case 0xCC>>2: /* 0xCC ADR - ADR */ /* LF */ - /* For machines with Base mode 0xCC08 stores base registers */ - if ((FC & 3) != 0) { /* must be word address */ - TRAPME = ADDRSPEC_TRAP; /* bad reg address, error */ - goto newpsd; /* go execute the trap now */ - } - temp = addr & 0xffe000; /* get 11 bit map # */ - bc = addr & 0x20; /* bit 26 initial value */ - while (reg < 8) { - if (bc != (addr & 0x20)) { /* test for crossing file boundry */ - if (CPU_MODEL < MODEL_27) { - TRAPME = ADDRSPEC_TRAP; /* bad reg address, error */ - goto newpsd; /* go execute the trap now */ - } - } - if (temp != (addr & 0xffe000)) { /* test for crossing map boundry */ - if (CPU_MODEL >= MODEL_V6) { - TRAPME = ADDRSPEC_TRAP; /* bad reg address, error */ - goto newpsd; /* go execute the trap now */ - } - } - if (FC & 0x4) /* LFBR? 0xCC08 */ - TRAPME = Mem_read(addr, &BR[reg]); /* read the base reg */ - else /* LF? 0xCC00 */ - TRAPME = Mem_read(addr, &GPR[reg]); /* read the GPR reg */ - if (TRAPME) /* TRAPME has error */ - goto newpsd; /* go execute the trap now */ - reg++; /* next reg to write */ - addr += 4; /* next addr */ - } - break; - - case 0xD0>>2: /* 0xD0 SD|ADR - INV */ /* LEA none basemode only */ - if (MODES & BASEBIT) - goto inv; /* invalid instruction in basemode */ - /* bc has last bits 0,1 for indirect addr of both 1 for no indirection */ - addr &= 0x3fffffff; /* clear bits 0-1 */ - addr |= bc; /* insert bits 0,1 values into address */ - if (FC & 0x4) - addr |= F_BIT; /* copy F bit from instruction */ - dest = (t_uint64)(addr); - break; - - case 0xD4>>2: /* 0xD4 RR|SM|ADR - RR|SM|ADR */ /* STx */ - break; - - case 0xD8>>2: /* 0xD8 RR|SM|ADR - RR|SM|ADR */ /* STMx */ - /* STMD needs both regs to be masked with R4 */ - if (dbl) { - /* we need to and both regs */ - t_uint64 nm = (((t_uint64)GPR[4]) << 32) | (((t_uint64)GPR[4]) & D32RMASK); - dest &= nm; /* mask both regs with reg 4 contents */ - } else { - dest &= (((t_uint64)GPR[4]) & D32RMASK); /* mask with reg 4 contents */ - } - break; - - case 0xDC>>2: /* 0xDC INV - ADR */ /* INV nonbasemode (STFx basemode) */ - /* DC00 STF */ /* DC08 STFBR */ - if ((FC & 0x4) && (CPU_MODEL <= MODEL_27)) { - /* basemode undefined for 32/7x & 32/27 */ - TRAPME = UNDEFINSTR_TRAP; /* Undefined Instruction Trap */ - if ((CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9)) - TRAPSTATUS |= BIT0; /* set bit 0 of trap status */ - goto newpsd; /* handle trap */ - } - /* For machines with Base mode 0xDC08 stores base registers */ - if ((FC & 3) != 0) { /* must be word address */ - TRAPME = ADDRSPEC_TRAP; /* bad reg address, error */ - goto newpsd; /* go execute the trap now */ - } - bc = addr & 0x20; /* bit 26 initial value */ - temp = addr & 0xffe000; /* get 11 bit map # */ - while (reg < 8) { - if (bc != (addr & 0x20)) { /* test for crossing file boundry */ - if (CPU_MODEL < MODEL_27) { - TRAPME = ADDRSPEC_TRAP; /* bad reg address, error */ - goto newpsd; /* go execute the trap now */ - } - } - if (temp != (addr & 0xffe000)) { /* test for crossing map boundry */ - if (CPU_MODEL >= MODEL_V6) { - TRAPME = ADDRSPEC_TRAP; /* bad reg address, error */ - goto newpsd; /* go execute the trap now */ - } - } - if (FC & 0x4) /* STFBR? */ - TRAPME = Mem_write(addr, &BR[reg]); /* store the base reg */ - else /* STF */ - TRAPME = Mem_write(addr, &GPR[reg]); /* store the GPR reg */ - if (TRAPME) /* TRAPME has error */ - goto newpsd; /* go execute the trap now */ - reg++; /* next reg to write */ - addr += 4; /* next addr */ - } - break; - - case 0xE0>>2: /* 0xE0 ADR - ADR */ /* ADFx, SUFx */ + case 0xE0>>2: /* 0xE0 ADR - ADR */ /* ADFx, SUFx */ if ((TRAPME = Mem_read(addr, &temp))) { /* get the word from memory */ - goto newpsd; /* memory read error or map fault */ + goto newpsd; /* memory read error or map fault */ } - source = (t_uint64)temp; /* make into 64 bit value */ - if (FC & 2) { /* see if double word addr */ + source = (t_uint64)temp; /* make into 64 bit value */ + if (FC & 2) { /* see if double word addr */ if ((TRAPME = Mem_read(addr+4, &temp))) { /* get the 2nd word from memory */ - goto newpsd; /* memory read error or map fault */ + goto newpsd; /* memory read error or map fault */ } source = (source << 32) | (t_uint64)temp; /* merge in the low order 32 bits */ - dbl = 1; /* double word instruction */ + dbl = 1; /* double word instruction */ } else { source |= (source & MSIGN) ? D32LMASK : 0; - dbl = 0; /* not double wd */ + dbl = 0; /* not double wd */ } - PSD1 &= 0x87FFFFFE; /* clear the old CC's */ - CC = 0; /* clear the CC'ss */ + PSD1 &= 0x87FFFFFE; /* clear the old CC's */ + CC = 0; /* clear the CC'ss */ /* handle float or double add/sub instructions */ if (dbl == 0) { /* do ADFW or SUFW instructions */ - temp2 = GPR[reg]; /* dest - reg contents specified by Rd */ + temp2 = GPR[reg]; /* dest - reg contents specified by Rd */ addr = (uint32)(source & D32RMASK); /* get 32 bits from source memory */ - if ((opr & 8) == 0) { /* Was it SUFW? */ - addr = NEGATE32(addr); /* take negative for add */ + if ((opr & 8) == 0) { /* Was it SUFW? */ + addr = NEGATE32(addr); /* take negative for add */ } temp = s_adfw(temp2, addr, &CC); /* do ADFW */ sim_debug(DEBUG_DETAIL, &cpu_dev, @@ -5683,439 +5649,435 @@ sim_debug(DEBUG_IRQ, &cpu_dev, ovr = 0; if (CC & CC1BIT) ovr = 1; - PSD1 |= (CC & 0x78000000); /* update the CC's in the PSD */ + PSD1 |= (CC & 0x78000000); /* update the CC's in the PSD */ /* check if we had an arithmetic exception on the last instruction*/ if (ovr && (MODES & AEXPBIT)) { /* leave regs unchanged */ - TRAPME = AEXPCEPT_TRAP; /* trap the system now */ - goto newpsd; /* process the trap */ + TRAPME = AEXPCEPT_TRAP; /* trap the system now */ + goto newpsd; /* process the trap */ } /* AEXP not enabled, so apply fix here */ /* return temp to destination reg */ - GPR[reg] = temp; /* dest - reg contents specified by Rd */ + GPR[reg] = temp; /* dest - reg contents specified by Rd */ } else { /* handle ADFD or SUFD */ - if (reg & 1) { /* see if odd reg specified */ - TRAPME = ADDRSPEC_TRAP; /* bad reg address, error */ - goto newpsd; /* go execute the trap now */ + if (reg & 1) { /* see if odd reg specified */ + TRAPME = ADDRSPEC_TRAP; /* bad reg address, error */ + goto newpsd; /* go execute the trap now */ } /* do ADFD or SUFD instructions */ td = (((t_uint64)GPR[reg]) << 32); /* get upper reg value */ - td |= (t_uint64)GPR[reg+1]; /* insert low order reg value */ + td |= (t_uint64)GPR[reg+1]; /* insert low order reg value */ /* source has 64 bit memory data */ - if ((opr & 8) == 0) { /* Was it SUFD? */ - source = NEGATE32(source); /* make negative for subtract */ + if ((opr & 8) == 0) { /* Was it SUFD? */ + source = NEGATE32(source); /* make negative for subtract */ } - dest = s_adfd(td, source, &CC); /* do ADFD */ + dest = s_adfd(td, source, &CC); /* do ADFD */ sim_debug(DEBUG_DETAIL, &cpu_dev, "%s GPR[%d] %08x %08x src %016llx result %016llx CC %08x\n", (opr&8) ? "ADFD":"SUFD", reg, GPR[reg], GPR[reg+1], source, dest, CC); ovr = 0; - if (CC & CC1BIT) /* test for overflow detection */ + if (CC & CC1BIT) /* test for overflow detection */ ovr = 1; - PSD1 |= (CC & 0x78000000); /* update the CC's in the PSD */ + PSD1 |= (CC & 0x78000000); /* update the CC's in the PSD */ /* check if we had an arithmetic exception on the last instruction */ if (ovr && (MODES & AEXPBIT)) { /* leave regs unchanged */ - TRAPME = AEXPCEPT_TRAP; /* trap the system now */ - goto newpsd; /* process the trap */ + TRAPME = AEXPCEPT_TRAP; /* trap the system now */ + goto newpsd; /* process the trap */ } /* dest will be returned to destination regs */ /* if AEXP not enabled, apply fix here */ /* return dest to destination reg */ GPR[reg] = (uint32)((dest & D32LMASK) >> 32); /* get upper reg value */ - GPR[reg+1] = (uint32)(dest & D32RMASK); /* get lower reg value */ + GPR[reg+1] = (uint32)(dest & D32RMASK); /* get lower reg value */ } break; - case 0xE4>>2: /* 0xE4 ADR - ADR */ /* MPFx, DVFx */ - if ((TRAPME = Mem_read(addr, &temp))) { /* get the word from memory */ - goto newpsd; /* memory read error or map fault */ + case 0xE4>>2: /* 0xE4 ADR - ADR */ /* MPFx, DVFx */ + if ((TRAPME = Mem_read(addr, &temp))) { /* get the word from memory */ + goto newpsd; /* memory read error or map fault */ + } + source = (t_uint64)temp; /* make into 64 bit value */ + if (FC & 2) { /* see if double word addr */ + if ((TRAPME = Mem_read(addr+4, &temp))) { /* get the 2nd word from memory */ + goto newpsd; /* memory read error or map fault */ } - source = (t_uint64)temp; /* make into 64 bit value */ - if (FC & 2) { /* see if double word addr */ - if ((TRAPME = Mem_read(addr+4, &temp))) { /* get the 2nd word from memory */ - goto newpsd; /* memory read error or map fault */ - } - source = (source << 32) | (t_uint64)temp; /* merge in the low order 32 bits */ - dbl = 1; /* double word instruction */ + source = (source << 32) | (t_uint64)temp; /* merge in the low order 32 bits */ + dbl = 1; /* double word instruction */ + } else { + source |= (source & MSIGN) ? D32LMASK : 0; + dbl = 0; /* not double wd */ + } + PSD1 &= 0x87FFFFFE; /* clear the old CC's */ + CC = 0; /* clear the CC'ss */ + /* handle float or double mul/div instructions */ + if (dbl == 0) { + /* do MPFW or DVFW instructions */ + temp2 = GPR[reg]; /* dest - reg contents specified by Rd */ + addr = (uint32)(source & D32RMASK); /* get 32 bits from source memory */ + if (opr & 8) { /* Was it MPFW? */ + temp = s_mpfw(temp2, addr, &CC); /* do MPFW */ } else { - source |= (source & MSIGN) ? D32LMASK : 0; - dbl = 0; /* not double wd */ + temp = (uint32)s_dvfw(temp2, addr, &CC); /* do DVFW */ } - PSD1 &= 0x87FFFFFE; /* clear the old CC's */ - CC = 0; /* clear the CC'ss */ - /* handle float or double mul/div instructions */ - if (dbl == 0) { - /* do MPFW or DVFW instructions */ - temp2 = GPR[reg]; /* dest - reg contents specified by Rd */ - addr = (uint32)(source & D32RMASK); /* get 32 bits from source memory */ - if (opr & 8) { /* Was it MPFW? */ - temp = s_mpfw(temp2, addr, &CC); /* do MPFW */ - } else { - temp = (uint32)s_dvfw(temp2, addr, &CC); /* do DVFW */ - } - sim_debug(DEBUG_DETAIL, &cpu_dev, - "%s GPR[%d] %08x addr %08x result %08x\n", - (opr&8) ? "MPFW":"DVFW", reg, GPR[reg], addr, temp); - if (CC & CC1BIT) - ovr = 1; - PSD1 |= (CC & 0x78000000); /* update the CC's in the PSD */ - /* check if we had an arithmetic exception on the last instruction*/ - if (ovr && (MODES & AEXPBIT)) { - /* leave regs unchanged */ - TRAPME = AEXPCEPT_TRAP; /* trap the system now */ - goto newpsd; /* process the trap */ - } - /* if AEXP not enabled, apply fix here */ - /* return temp to destination reg */ - GPR[reg] = temp; /* dest - reg contents specified by Rd */ + sim_debug(DEBUG_DETAIL, &cpu_dev, + "%s GPR[%d] %08x addr %08x result %08x\n", + (opr&8) ? "MPFW":"DVFW", reg, GPR[reg], addr, temp); + if (CC & CC1BIT) + ovr = 1; + PSD1 |= (CC & 0x78000000); /* update the CC's in the PSD */ + /* check if we had an arithmetic exception on the last instruction*/ + if (ovr && (MODES & AEXPBIT)) { + /* leave regs unchanged */ + TRAPME = AEXPCEPT_TRAP; /* trap the system now */ + goto newpsd; /* process the trap */ + } + /* if AEXP not enabled, apply fix here */ + /* return temp to destination reg */ + GPR[reg] = temp; /* dest - reg contents specified by Rd */ + } else { + /* handle MPFD or DVFD */ + if (reg & 1) { /* see if odd reg specified */ + TRAPME = ADDRSPEC_TRAP; /* bad reg address, error */ + goto newpsd; /* go execute the trap now */ + } + /* do MPFD or DVFD instructions */ + td = (((t_uint64)GPR[reg]) << 32); /* get upper reg value */ + td |= (t_uint64)GPR[reg+1]; /* insert low order reg value */ + /* source has 64 bit memory data */ + if (opr & 8) { /* Was it MPFD? */ + dest = s_mpfd(td, source, &CC); /* do MPFD */ } else { - /* handle MPFD or DVFD */ - if (reg & 1) { /* see if odd reg specified */ - TRAPME = ADDRSPEC_TRAP; /* bad reg address, error */ - goto newpsd; /* go execute the trap now */ - } - /* do MPFD or DVFD instructions */ - td = (((t_uint64)GPR[reg]) << 32); /* get upper reg value */ - td |= (t_uint64)GPR[reg+1]; /* insert low order reg value */ - /* source has 64 bit memory data */ - if (opr & 8) { /* Was it MPFD? */ - dest = s_mpfd(td, source, &CC); /* do MPFD */ - } else { - dest = s_dvfd(td, source, &CC); /* do DVFD */ - } - sim_debug(DEBUG_DETAIL, &cpu_dev, - "%s GPR[%d] %08x %08x src %016llx result %016llx\n", - (opr&8) ? "MPFD":"DVFD", reg, GPR[reg], GPR[reg+1], source, dest); - if (CC & CC1BIT) /* test for overflow detection */ - ovr = 1; - PSD1 |= (CC & 0x78000000); /* update the CC's in the PSD */ - /* check if we had an arithmetic exception on the last instruction*/ - if (ovr && (MODES & AEXPBIT)) { - /* leave regs unchanged */ - TRAPME = AEXPCEPT_TRAP; /* trap the system now */ - goto newpsd; /* process the trap */ - } - /* dest will be returned to destination regs */ - /* if AEXP not enabled, apply fix here */ - /* return dest to destination reg */ - GPR[reg] = (uint32)((dest & D32LMASK) >> 32); /* get upper reg value */ - GPR[reg+1] = (uint32)(dest & D32RMASK); /* get lower reg value */ + dest = s_dvfd(td, source, &CC); /* do DVFD */ } - break; + sim_debug(DEBUG_DETAIL, &cpu_dev, + "%s GPR[%d] %08x %08x src %016llx result %016llx\n", + (opr&8) ? "MPFD":"DVFD", reg, GPR[reg], GPR[reg+1], source, dest); + if (CC & CC1BIT) /* test for overflow detection */ + ovr = 1; + PSD1 |= (CC & 0x78000000); /* update the CC's in the PSD */ + /* check if we had an arithmetic exception on the last instruction*/ + if (ovr && (MODES & AEXPBIT)) { + /* leave regs unchanged */ + TRAPME = AEXPCEPT_TRAP; /* trap the system now */ + goto newpsd; /* process the trap */ + } + /* dest will be returned to destination regs */ + /* if AEXP not enabled, apply fix here */ + /* return dest to destination reg */ + GPR[reg] = (uint32)((dest & D32LMASK) >> 32); /* get upper reg value */ + GPR[reg+1] = (uint32)(dest & D32RMASK); /* get lower reg value */ + } + break; - case 0xE8>>2: /* 0xE8 SM|RR|RNX|ADR - SM|RM|ADR */ /* ARMx */ - ovr = 0; - CC = 0; - switch(FC) { /* adjust for hw or bytes */ - case 4: case 5: case 6: case 7: /* byte address */ - /* ARMB */ - td = dest + source; /* DO ARMB */ - td &= 0xff; /* mask out right most byte */ - dest &= 0xffffff00; /* make place for byte */ - dest |= td; /* insert result into dest */ - if (td == 0) - CC |= CC4BIT; /* byte is zero, so CC4 */ - break; - case 1: /* left halfword addr */ - case 3: /* right halfword addr */ - /* ARMH */ - td = dest + source; /* DO ARMH */ - td &= RMASK; /* mask out right most 16 bits */ - dest &= LMASK; /* make place for halfword */ - dest |= td; /* insert result into dest */ - if (td == 0) - CC |= CC4BIT; /* hw is zero, so CC4 */ - break; - case 0: /* 32 bit word */ - /* ARMW */ - /* dest and source are really 32 bit values */ - t = (source & MSIGN) != 0; - t |= ((dest & MSIGN) != 0) ? 2 : 0; - td = dest + source; /* DO ARMW */ - td &= D32RMASK; /* mask out right most 32 bits */ - dest = 0; /* make place for 64 bits */ - dest |= td; /* insert result into dest */ - /* if both signs are neg and result sign is positive, overflow */ - /* if both signs are pos and result sign is negative, overflow */ - if (((t == 3) && ((dest & MSIGN) == 0)) || - ((t == 0) && ((dest & MSIGN) != 0))) - ovr = 1; - if (dest & MSIGN) - dest = (D32LMASK | dest); /* sign extend */ - else - dest = (D32RMASK & dest); /* zero fill */ - if (td == 0) - CC |= CC4BIT; /* word is zero, so CC4 */ - else + case 0xE8>>2: /* 0xE8 SM|RR|RNX|ADR - SM|RM|ADR */ /* ARMx */ + ovr = 0; + CC = 0; + switch(FC) { /* adjust for hw or bytes */ + case 4: case 5: case 6: case 7: /* byte address */ + /* ARMB */ + td = dest + source; /* DO ARMB */ + td &= 0xff; /* mask out right most byte */ + dest &= 0xffffff00; /* make place for byte */ + dest |= td; /* insert result into dest */ + if (td == 0) + CC |= CC4BIT; /* byte is zero, so CC4 */ + break; + case 1: /* left halfword addr */ + case 3: /* right halfword addr */ + /* ARMH */ + td = dest + source; /* DO ARMH */ + td &= RMASK; /* mask out right most 16 bits */ + dest &= LMASK; /* make place for halfword */ + dest |= td; /* insert result into dest */ + if (td == 0) + CC |= CC4BIT; /* hw is zero, so CC4 */ + break; + case 0: /* 32 bit word */ + /* ARMW */ + /* dest and source are really 32 bit values */ + t = (source & MSIGN) != 0; + t |= ((dest & MSIGN) != 0) ? 2 : 0; + td = dest + source; /* DO ARMW */ + td &= D32RMASK; /* mask out right most 32 bits */ + dest = 0; /* make place for 64 bits */ + dest |= td; /* insert result into dest */ + /* if both signs are neg and result sign is positive, overflow */ + /* if both signs are pos and result sign is negative, overflow */ + if (((t == 3) && ((dest & MSIGN) == 0)) || + ((t == 0) && ((dest & MSIGN) != 0))) + ovr = 1; + if (dest & MSIGN) + dest = (D32LMASK | dest); /* sign extend */ + else + dest = (D32RMASK & dest); /* zero fill */ + if (td == 0) + CC |= CC4BIT; /* word is zero, so CC4 */ + else if (td & 0x80000000) CC |= CC3BIT; /* it is neg wd, so CC3 */ else CC |= CC2BIT; /* then td > 0, so CC2 */ - break; - case 2: /* 64 bit double */ - /* ARMD */ - t = (source & DMSIGN) != 0; - t |= ((dest & DMSIGN) != 0) ? 2 : 0; - td = dest + source; /* DO ARMD */ - dest = td; /* insert result into dest */ - /* if both signs are neg and result sign is positive, overflow */ - /* if both signs are pos and result sign is negative, overflow */ - if (((t == 3) && ((dest & DMSIGN) == 0)) || - ((t == 0) && ((dest & DMSIGN) != 0))) - ovr = 1; - if (td == 0) - CC |= CC4BIT; /* dw is zero, so CC4 */ - else + break; + case 2: /* 64 bit double */ + /* ARMD */ + t = (source & DMSIGN) != 0; + t |= ((dest & DMSIGN) != 0) ? 2 : 0; + td = dest + source; /* DO ARMD */ + dest = td; /* insert result into dest */ + /* if both signs are neg and result sign is positive, overflow */ + /* if both signs are pos and result sign is negative, overflow */ + if (((t == 3) && ((dest & DMSIGN) == 0)) || + ((t == 0) && ((dest & DMSIGN) != 0))) + ovr = 1; + if (td == 0) + CC |= CC4BIT; /* dw is zero, so CC4 */ + else if (td & DMSIGN) CC |= CC3BIT; /* it is neg dw, so CC3 */ else CC |= CC2BIT; /* then td > 0, so CC2 */ break; - } - if (ovr) - CC |= CC1BIT; /* set overflow CC */ - PSD1 &= 0x87FFFFFE; /* clear the old CC's from PSD1 */ - PSD1 |= CC; /* update the CC's in the PSD */ - /* the arithmetic exception will be handled */ - /* after instruction is completed */ - /* check for arithmetic exception trap enabled */ - if (ovr && (MODES & AEXPBIT)) { - TRAPME = AEXPCEPT_TRAP; /* set the trap type */ - } - break; + } + if (ovr) + CC |= CC1BIT; /* set overflow CC */ + PSD1 &= 0x87FFFFFE; /* clear the old CC's from PSD1 */ + PSD1 |= CC; /* update the CC's in the PSD */ + /* the arithmetic exception will be handled */ + /* after instruction is completed */ + /* check for arithmetic exception trap enabled */ + if (ovr && (MODES & AEXPBIT)) { + TRAPME = AEXPCEPT_TRAP; /* set the trap type */ + } + break; - case 0xEC>>2: /* 0xEC ADR - ADR */ /* Branch unconditional or Branch True */ - /* GOOF alert, the assembler sets bit 31 to 1 so this test will fail*/ - /* so just test for F bit and go on */ - /* if ((FC & 5) != 0) { */ - if ((FC & 4) != 0) { - TRAPME = ADDRSPEC_TRAP; /* bad address, error */ - sim_debug(DEBUG_TRAP, &cpu_dev, - "ADDRSPEC10 OP %04x addr %08x\n", OP, addr); - goto newpsd; /* go execute the trap now */ - } - temp2 = CC; /* save the old CC's */ - CC = PSD1 & 0x78000000; /* get CC's if any */ - switch(reg) { - case 0: t = 1; break; - case 1: t = (CC & CC1BIT) != 0; break; - case 2: t = (CC & CC2BIT) != 0; break; - case 3: t = (CC & CC3BIT) != 0; break; - case 4: t = (CC & CC4BIT) != 0; break; - case 5: t = (CC & (CC2BIT|CC4BIT)) != 0; break; - case 6: t = (CC & (CC3BIT|CC4BIT)) != 0; break; - case 7: t = (CC & (CC1BIT|CC2BIT|CC3BIT|CC4BIT)) != 0; break; - } - if (t) { /* see if we are going to branch */ - /* we are taking the branch, set CC's if indirect, else leave'm */ - /* update the PSD with new address */ - PSD1 = (PSD1 & 0xff000000) | (addr & 0xfffffe); /* set new PC */ - i_flags |= BT; /* we branched, so no PC update */ - if (((MODES & BASEBIT) == 0) && (IR & IND)) /* see if CCs from last indirect wanted */ - PSD1 = (PSD1 & 0x87fffffe) | temp2; /* insert last indirect CCs */ -/*FIX F77*/ if ((MODES & (BASEBIT|EXTDBIT)) == 0) /* see if basemode */ -/*FIX F77*/ PSD1 &= 0xff07ffff; /* only 19 bit address allowed */ - } - /* branch not taken, go do next instruction */ - break; + case 0xEC>>2: /* 0xEC ADR - ADR */ /* Branch unconditional or Branch True */ + /* GOOF alert, the assembler sets bit 31 to 1 so this test will fail*/ + /* so just test for F bit and go on */ + /* if ((FC & 5) != 0) { */ + if ((FC & 4) != 0) { + TRAPME = ADDRSPEC_TRAP; /* bad address, error */ + sim_debug(DEBUG_TRAP, &cpu_dev, + "ADDRSPEC10 OP %04x addr %08x\n", OP, addr); + goto newpsd; /* go execute the trap now */ + } + temp2 = CC; /* save the old CC's */ + CC = PSD1 & 0x78000000; /* get CC's if any */ + switch(reg) { + case 0: t = 1; break; + case 1: t = (CC & CC1BIT) != 0; break; + case 2: t = (CC & CC2BIT) != 0; break; + case 3: t = (CC & CC3BIT) != 0; break; + case 4: t = (CC & CC4BIT) != 0; break; + case 5: t = (CC & (CC2BIT|CC4BIT)) != 0; break; + case 6: t = (CC & (CC3BIT|CC4BIT)) != 0; break; + case 7: t = (CC & (CC1BIT|CC2BIT|CC3BIT|CC4BIT)) != 0; break; + } + if (t) { /* see if we are going to branch */ + /* we are taking the branch, set CC's if indirect, else leave'm */ + /* update the PSD with new address */ + PSD1 = (PSD1 & 0xff000000) | (addr & 0xfffffe); /* set new PC */ + i_flags |= BT; /* we branched, so no PC update */ + if (((MODES & BASEBIT) == 0) && (IR & IND)) /* see if CCs from last indirect wanted */ + PSD1 = (PSD1 & 0x87fffffe) | temp2; /* insert last indirect CCs */ +/*FIX F77*/ if ((MODES & (BASEBIT|EXTDBIT)) == 0) /* see if basemode */ +/*FIX F77*/ PSD1 &= 0xff07ffff; /* only 19 bit address allowed */ + } + /* branch not taken, go do next instruction */ + break; - case 0xF0>>2: /* 0xF0 ADR - ADR */ /* Branch False or Branch Function True BFT */ - /* GOOF alert, the assembler sets bit 31 to 1 so this test will fail*/ - /* so just test for F bit and go on */ - /* if ((FC & 5) != 0) { */ - if ((FC & 4) != 0) { - TRAPME = ADDRSPEC_TRAP; /* bad address, error */ - sim_debug(DEBUG_TRAP, &cpu_dev, - "ADDRSPEC11 OP %04x addr %08x\n", OP, addr); - goto newpsd; /* go execute the trap now */ - } - temp2 = CC; /* save the old CC's */ - CC = PSD1 & 0x78000000; /* get CC's if any */ - switch(reg) { - case 0: t = (GPR[4] & (0x8000 >> ((CC >> 27) & 0xf))) != 0; break; - case 1: t = (CC & CC1BIT) == 0; break; - case 2: t = (CC & CC2BIT) == 0; break; - case 3: t = (CC & CC3BIT) == 0; break; - case 4: t = (CC & CC4BIT) == 0; break; - case 5: t = (CC & (CC2BIT|CC4BIT)) == 0; break; - case 6: t = (CC & (CC3BIT|CC4BIT)) == 0; break; - case 7: t = (CC & (CC1BIT|CC2BIT|CC3BIT|CC4BIT)) == 0; break; - } - if (t) { /* see if we are going to branch */ - /* we are taking the branch, set CC's if indirect, else leave'm */ - /* update the PSD with new address */ - PSD1 = (PSD1 & 0xff000000) | (addr & 0xfffffe); /* set new PC */ - i_flags |= BT; /* we branched, so no PC update */ - if (((MODES & BASEBIT) == 0) && (IR & IND)) /* see if CCs from last indirect wanted */ - PSD1 = (PSD1 & 0x87fffffe) | temp2; /* insert last indirect CCs */ -/*FIX F77*/ if ((MODES & (BASEBIT|EXTDBIT)) == 0) /* see if basemode */ -/*FIX F77*/ PSD1 &= 0xff07ffff; /* only 19 bit address allowed */ - } - break; + case 0xF0>>2: /* 0xF0 ADR - ADR */ /* Branch False or Branch Function True BFT */ + /* GOOF alert, the assembler sets bit 31 to 1 so this test will fail*/ + /* so just test for F bit and go on */ + /* if ((FC & 5) != 0) { */ + if ((FC & 4) != 0) { + TRAPME = ADDRSPEC_TRAP; /* bad address, error */ + sim_debug(DEBUG_TRAP, &cpu_dev, + "ADDRSPEC11 OP %04x addr %08x\n", OP, addr); + goto newpsd; /* go execute the trap now */ + } + temp2 = CC; /* save the old CC's */ + CC = PSD1 & 0x78000000; /* get CC's if any */ + switch(reg) { + case 0: t = (GPR[4] & (0x8000 >> ((CC >> 27) & 0xf))) != 0; break; + case 1: t = (CC & CC1BIT) == 0; break; + case 2: t = (CC & CC2BIT) == 0; break; + case 3: t = (CC & CC3BIT) == 0; break; + case 4: t = (CC & CC4BIT) == 0; break; + case 5: t = (CC & (CC2BIT|CC4BIT)) == 0; break; + case 6: t = (CC & (CC3BIT|CC4BIT)) == 0; break; + case 7: t = (CC & (CC1BIT|CC2BIT|CC3BIT|CC4BIT)) == 0; break; + } + if (t) { /* see if we are going to branch */ + /* we are taking the branch, set CC's if indirect, else leave'm */ + /* update the PSD with new address */ + PSD1 = (PSD1 & 0xff000000) | (addr & 0xfffffe); /* set new PC */ + i_flags |= BT; /* we branched, so no PC update */ + if (((MODES & BASEBIT) == 0) && (IR & IND)) /* see if CCs from last indirect wanted */ + PSD1 = (PSD1 & 0x87fffffe) | temp2; /* insert last indirect CCs */ +/*FIX F77*/ if ((MODES & (BASEBIT|EXTDBIT)) == 0) /* see if basemode */ +/*FIX F77*/ PSD1 &= 0xff07ffff; /* only 19 bit address allowed */ + } + break; - case 0xF4>>2: /* 0xF4 RR|SD|ADR - RR|SB|WRD */ /* Branch increment */ - dest += ((t_uint64)1) << ((IR >> 21) & 3);/* use bits 9 & 10 to incr reg */ - if (dest != 0) { /* if reg is not 0, take the branch */ - /* we are taking the branch, set CC's if indirect, else leave'm */ - /* update the PSD with new address */ + case 0xF4>>2: /* 0xF4 RR|SD|ADR - RR|SB|WRD */ /* Branch increment */ + dest += ((t_uint64)1) << ((IR >> 21) & 3); /* use bits 9 & 10 to incr reg */ + if (dest != 0) { /* if reg is not 0, take the branch */ + /* we are taking the branch, set CC's if indirect, else leave'm */ + /* update the PSD with new address */ -#if 0 /* set #if to 1 to stop branch to self while tracing, for now */ - if (PC == (addr & 0xFFFFFC)) { /* BIB to current PC, bump branch addr */ - addr += 4; -// fprintf(stderr, "BI? stopping BIB $ addr %x PC %x\r\n", addr, PC); - dest = 0; /* force reg to zero */ - } +#if 0 /* set #if to 1 to stop branch to self while tracing, for now */ + if (PC == (addr & 0xFFFFFC)) { /* BIB to current PC, bump branch addr */ + addr += 4; +// fprintf(stderr, "BI? stopping BIB $ addr %x PC %x\r\n", addr, PC); + dest = 0; /* force reg to zero */ + } #endif - PSD1 = (PSD1 & 0xff000000) | (addr & 0xfffffe); /* set new PC */ - if (((MODES & BASEBIT) == 0) && (IR & IND)) /* see if CCs from last indirect wanted */ - PSD1 = (PSD1 & 0x87fffffe) | CC; /* insert last CCs */ - i_flags |= BT; /* we branched, so no PC update */ -/*FIX F77*/ if ((MODES & (BASEBIT|EXTDBIT)) == 0) /* see if basemode */ -/*FIX F77*/ PSD1 &= 0xff07ffff; /* only 19 bit address allowed */ - } + PSD1 = (PSD1 & 0xff000000) | (addr & 0xfffffe); /* set new PC */ + if (((MODES & BASEBIT) == 0) && (IR & IND)) /* see if CCs from last indirect wanted */ + PSD1 = (PSD1 & 0x87fffffe) | CC; /* insert last CCs */ + i_flags |= BT; /* we branched, so no PC update */ +/*FIX F77*/ if ((MODES & (BASEBIT|EXTDBIT)) == 0) /* see if basemode */ +/*FIX F77*/ PSD1 &= 0xff07ffff; /* only 19 bit address allowed */ + } + break; + + case 0xF8>>2: /* 0xF8 SM|ADR - SM|ADR */ /* ZMx, BL, BRI, LPSD, LPSDCM, TPR, TRP */ + switch((opr >> 7) & 0x7) { /* use bits 6-8 to determine instruction */ + case 0x0: /* ZMx F80x */ /* SM */ + dest = 0; /* destination value is zero */ + i_flags |= SM; /* SM not set so set it to store value */ + break; + case 0x1: /* BL F880 */ + /* copy CC's from instruction and PC incremented by 4 */ + GPR[0] = ((PSD1 & 0xff000000) | ((PSD1 + 4) & 0xfffffe)); + if (((MODES & BASEBIT) == 0) && (IR & IND)) /* see if CCs from last indirect wanted */ + PSD1 = (PSD1 & 0x87fffffe) | CC; /* insert last CCs */ + /* update the PSD with new address */ + if (MODES & BASEBIT) + PSD1 = (PSD1 & 0xff000000) | (addr & 0xfffffe); /* bit 8-30 */ + else + PSD1 = (PSD1 & 0xff000000) | (addr & 0x07fffe); /* bit 13-30 */ + i_flags |= BT; /* we branched, so no PC update */ +/*FIX F77*/ if ((MODES & (BASEBIT|EXTDBIT)) == 0) /* see if basemode */ +/*FIX F77*/ PSD1 &= 0xff07ffff; /* only 19 bit address allowed */ break; - case 0xF8>>2: /* 0xF8 SM|ADR - SM|ADR */ /* ZMx, BL, BRI, LPSD, LPSDCM, TPR, TRP */ - switch((opr >> 7) & 0x7) { /* use bits 6-8 to determine instruction */ - case 0x0: /* ZMx F80x */ /* SM */ - dest = 0; /* destination value is zero */ - i_flags |= SM; /* SM not set so set it to store value */ - break; - case 0x1: /* BL F880 */ - /* copy CC's from instruction and PC incremented by 4 */ - GPR[0] = ((PSD1 & 0xff000000) | ((PSD1 + 4) & 0xfffffe)); - if (((MODES & BASEBIT) == 0) && (IR & IND)) /* see if CCs from last indirect wanted */ - PSD1 = (PSD1 & 0x87fffffe) | CC; /* insert last CCs */ - /* update the PSD with new address */ - if (MODES & BASEBIT) - PSD1 = (PSD1 & 0xff000000) | (addr & 0xfffffe); /* bit 8-30 */ + case 0x3: /* LPSD F980 */ + /* fall through */; + case 0x5: /* LPSDCM FA80 */ + irq_pend = 1; /* start scanning interrupts again */ + if ((MODES & PRIVBIT) == 0) { /* must be privileged */ + TRAPME = PRIVVIOL_TRAP; /* set the trap to take */ + if ((CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9)) + TRAPSTATUS |= BIT0; /* set bit 0 of trap status */ else - PSD1 = (PSD1 & 0xff000000) | (addr & 0x07fffe); /* bit 13-30 */ - i_flags |= BT; /* we branched, so no PC update */ -/*FIX F77*/ if ((MODES & (BASEBIT|EXTDBIT)) == 0) /* see if basemode */ -/*FIX F77*/ PSD1 &= 0xff07ffff; /* only 19 bit address allowed */ - break; - - case 0x3: /* LPSD F980 */ - /* fall through */; - case 0x5: /* LPSDCM FA80 */ -/*0904*/ irq_pend = 1; /* start scanning interrupts again */ - if ((MODES & PRIVBIT) == 0) { /* must be privileged */ -//sim_debug(DEBUG_EXP, &cpu_dev, "Privledged violation LPSD(CM)\n"); - TRAPME = PRIVVIOL_TRAP; /* set the trap to take */ - if ((CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9)) - TRAPSTATUS |= BIT0; /* set bit 0 of trap status */ - else - TRAPSTATUS |= BIT19; /* set bit 19 of trap status */ - goto newpsd; /* Privlege violation trap */ - } - CPUSTATUS |= 0x40; /* enable software traps */ - /* this will allow attn and */ - /* power fail traps */ - if ((FC & 04) != 0 || FC == 2) { /* can not be byte or doubleword */ - /* Fault */ - TRAPME = ADDRSPEC_TRAP; /* bad reg address, error */ - sim_debug(DEBUG_TRAP, &cpu_dev, - "ADDRSPEC12 OP %04x addr %08x\n", OP, addr); - goto newpsd; /* go execute the trap now */ - } - if ((TRAPME = Mem_read(addr, &temp))) { /* get PSD1 from memory */ - if ((CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9)) { - TRAPSTATUS |= BIT10; /* set bit 10 of trap status */ - TRAPSTATUS |= BIT7; /* set bit 7 of trap status */ - } else - TRAPSTATUS |= BIT18; /* set bit 18 of trap status */ - goto newpsd; /* memory read error or map fault */ - } - bc = CPUSTATUS; /* save the CPU STATUS */ - TPSD[0] = PSD1; /* save the PSD for the instruction */ - TPSD[1] = PSD2; - t = MODES; /* save modes too */ - ix = SPAD[0xf5]; /* save the current PSD2 */ - reg = irq_pend; /* save intr status */ - - if (opr & 0x0200) { /* Was it LPSDCM? */ - if ((TRAPME = Mem_read(addr+4, &temp2))) { /* get PSD2 from memory */ - if ((CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9)) { - TRAPSTATUS |= BIT10; /* set bit 10 of trap status */ - TRAPSTATUS |= BIT7; /* set bit 7 of trap status */ - } else - TRAPSTATUS |= BIT18; /* set bit 18 of trap status */ - goto newpsd; /* memory read error or map fault */ - } -//0120 PSD2 = temp2; /* PSD2 access good, so save it */ - PSD2 = temp2 & 0xfffffff8; /* PSD2 access good, clean & ave it */ - } else { - if ((TRAPME = Mem_read(addr+4, &temp2))) { /* get PSD2 from memory */ - if ((CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9)) { - TRAPSTATUS |= BIT10; /* set bit 10 of trap status */ - TRAPSTATUS |= BIT7; /* set bit 7 of trap status */ - } else - TRAPSTATUS |= BIT18; /* set bit 18 of trap status */ - goto newpsd; /* memory read error or map fault */ - } - /* lpsd can not change cpix, so keep it */ -//0120 PSD2 = ((PSD2 & 0x3fff) | (temp2 & 0xffffc000)); /* use current cpix */ - PSD2 = ((PSD2 & 0x3ff8) | (temp2 & 0xffffc000)); /* use current cpix */ - } - PSD1 = temp; /* PSD1 good, so set it */ -#ifdef NOT_NOW -// sim_debug(DEBUG_DETAIL, &cpu_dev, - sim_debug(DEBUG_IRQ, &cpu_dev, - "LPSD(CM) load New PSD1 %08x PSD2 %08x\n", PSD1, PSD2); - for (ii=0; ii<8; ii+=2) { - sim_debug(DEBUG_IRQ, &cpu_dev, - "LPSD(CM) GPR[%d] %.8x GPR[%d] %.8x\n", ii, GPR[ii], ii+1, GPR[ii+1]); - } -#endif - /* set the mode bits and CCs from the new PSD */ - CC = PSD1 & 0x78000000; /* extract bits 1-4 from PSD1 */ - MODES = PSD1 & 0x87000000; /* extract bits 0, 5, 6, 7 from PSD 1 */ - CPUSTATUS &= ~0x87000000; /* reset bits in CPUSTATUS */ - CPUSTATUS |= MODES; /* now insert into CPUSTATUS */ - - /* set new map mode and interrupt blocking state in CPUSTATUS */ - if (PSD2 & MAPBIT) { - CPUSTATUS |= BIT8; /* set bit 8 of cpu status */ - MODES |= MAPMODE; /* set mapped mode */ + TRAPSTATUS |= BIT19; /* set bit 19 of trap status */ + goto newpsd; /* Privlege violation trap */ + } + CPUSTATUS |= 0x40; /* enable software traps */ + /* this will allow attn and */ + /* power fail traps */ + if ((FC & 04) != 0 || FC == 2) { /* can not be byte or doubleword */ + /* Fault */ + TRAPME = ADDRSPEC_TRAP; /* bad reg address, error */ + sim_debug(DEBUG_TRAP, &cpu_dev, + "ADDRSPEC12 OP %04x addr %08x\n", OP, addr); + goto newpsd; /* go execute the trap now */ + } + if ((TRAPME = Mem_read(addr, &temp))) { /* get PSD1 from memory */ + if ((CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9)) { + TRAPSTATUS |= BIT10; /* set bit 10 of trap status */ + TRAPSTATUS |= BIT7; /* set bit 7 of trap status */ } else - CPUSTATUS &= ~BIT8; /* reset bit 8 of cpu status */ + TRAPSTATUS |= BIT18; /* set bit 18 of trap status */ + goto newpsd; /* memory read error or map fault */ + } + bc = CPUSTATUS; /* save the CPU STATUS */ + TPSD[0] = PSD1; /* save the PSD for the instruction */ + TPSD[1] = PSD2; + t = MODES; /* save modes too */ + ix = SPAD[0xf5]; /* save the current PSD2 */ + reg = irq_pend; /* save intr status */ - /* set interrupt blocking state */ - if ((PSD2 & RETBBIT) == 0) { /* is it retain blocking state */ - if (PSD2 & SETBBIT) { /* no, is it set blocking state */ - CPUSTATUS |= BIT24; /* yes, set blk state in cpu status bit 24 */ - MODES |= BLKMODE; /* set blocked mode */ - } else { - CPUSTATUS &= ~BIT24; /* no, reset blk state in cpu status bit 24 */ - MODES &= ~BLKMODE; /* reset blocked mode */ - irq_pend = 1; /* start scanning interrupts again */ -#ifdef LEAVE_ACTIVE - if (irq_auto) { -/*AIR*/ INTS[irq_auto] &= ~INTS_ACT; /* deactivate specified int level */ -/*AIR*/ SPAD[irq_auto+0x80] &= ~SINT_ACT; /* deactivate in SPAD too */ - sim_debug(DEBUG_IRQ, &cpu_dev, - "<|>IntX deactivate level %02x at LPSD(CM) %08x %08x\n", - irq_auto, PSD1, PSD2); -/*AIR*/ irq_auto = 0; /* show done processing in blocked mode */ -/*103020*/ skipinstr = 1; /* skip interrupt test */ - } -#endif - } - } else { - /* set new blocking state in PSD2 */ - PSD2 &= ~(SETBBIT|RETBBIT); /* clear bit 48 & 49 to be unblocked */ - MODES &= ~(BLKMODE|RETMODE); /* reset blocked & retain mode bits */ - if (bc & BIT24) { /* see if old mode is blocked */ - PSD2 |= SETBBIT; /* set to blocked state */ - MODES |= BLKMODE; /* set blocked mode */ - } + if (opr & 0x0200) { /* Was it LPSDCM? */ + if ((TRAPME = Mem_read(addr+4, &temp2))) { /* get PSD2 from memory */ + if ((CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9)) { + TRAPSTATUS |= BIT10; /* set bit 10 of trap status */ + TRAPSTATUS |= BIT7; /* set bit 7 of trap status */ + } else + TRAPSTATUS |= BIT18; /* set bit 18 of trap status */ + goto newpsd; /* memory read error or map fault */ } + PSD2 = temp2 & 0xfffffff8; /* PSD2 access good, clean & ave it */ + } else { + if ((TRAPME = Mem_read(addr+4, &temp2))) { /* get PSD2 from memory */ + if ((CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9)) { + TRAPSTATUS |= BIT10; /* set bit 10 of trap status */ + TRAPSTATUS |= BIT7; /* set bit 7 of trap status */ + } else + TRAPSTATUS |= BIT18; /* set bit 18 of trap status */ + goto newpsd; /* memory read error or map fault */ + } + /* lpsd can not change cpix, so keep it */ + PSD2 = ((PSD2 & 0x3ff8) | (temp2 & 0xffffc000)); /* use current cpix */ + } + PSD1 = temp; /* PSD1 good, so set it */ +#ifdef MPXTEST + sim_debug(DEBUG_IRQ, &cpu_dev, + "LPSD(CM) load New PSD1 %08x PSD2 %08x\n", PSD1, PSD2); + for (ii=0; ii<8; ii+=2) { + sim_debug(DEBUG_IRQ, &cpu_dev, + "LPSD(CM) GPR[%d] %.8x GPR[%d] %.8x\n", ii, GPR[ii], ii+1, GPR[ii+1]); + } +#endif + /* set the mode bits and CCs from the new PSD */ + CC = PSD1 & 0x78000000; /* extract bits 1-4 from PSD1 */ + MODES = PSD1 & 0x87000000; /* extract bits 0, 5, 6, 7 from PSD 1 */ + CPUSTATUS &= ~0x87000000; /* reset bits in CPUSTATUS */ + CPUSTATUS |= MODES; /* now insert into CPUSTATUS */ -#ifdef MPXTEST /* set to 1 for traceme to work */ - /* get current MPX task name */ + /* set new map mode and interrupt blocking state in CPUSTATUS */ + if (PSD2 & MAPBIT) { + CPUSTATUS |= BIT8; /* set bit 8 of cpu status */ + MODES |= MAPMODE; /* set mapped mode */ + } else + CPUSTATUS &= ~BIT8; /* reset bit 8 of cpu status */ + + /* set interrupt blocking state */ + if ((PSD2 & RETBBIT) == 0) { /* is it retain blocking state */ + if (PSD2 & SETBBIT) { /* no, is it set blocking state */ + CPUSTATUS |= BIT24; /* yes, set blk state in cpu status bit 24 */ + MODES |= BLKMODE; /* set blocked mode */ + } else { + CPUSTATUS &= ~BIT24; /* no, reset blk state in cpu status bit 24 */ + MODES &= ~BLKMODE; /* reset blocked mode */ + irq_pend = 1; /* start scanning interrupts again */ +#ifdef LEAVE_ACTIVE + if (irq_auto) { +/*AIR*/ INTS[irq_auto] &= ~INTS_ACT; /* deactivate specified int level */ +/*AIR*/ SPAD[irq_auto+0x80] &= ~SINT_ACT; /* deactivate in SPAD too */ + sim_debug(DEBUG_IRQ, &cpu_dev, + "<|>IntX deactivate level %02x at LPSD(CM) %08x %08x\n", + irq_auto, PSD1, PSD2); +/*AIR*/ irq_auto = 0; /* show done processing in blocked mode */ + skipinstr = 1; /* skip interrupt test */ + } +#endif + } + } else { + /* set new blocking state in PSD2 */ + PSD2 &= ~(SETBBIT|RETBBIT); /* clear bit 48 & 49 to be unblocked */ + MODES &= ~(BLKMODE|RETMODE); /* reset blocked & retain mode bits */ + if (bc & BIT24) { /* see if old mode is blocked */ + PSD2 |= SETBBIT; /* set to blocked state */ + MODES |= BLKMODE; /* set blocked mode */ + } + } + +#ifdef MPXTEST /* set to 1 for traceme to work */ + /* get current MPX task name */ { int j; char n[9]; @@ -6126,7 +6088,7 @@ sim_debug(DEBUG_IRQ, &cpu_dev, n[j] = 0x20; } n[8] = 0; - if (opr & 0x0200) { /* Was it LPSDCM? */ + if (opr & 0x0200) { /* Was it LPSDCM? */ sim_debug(DEBUG_IRQ, &cpu_dev, "LPSDCM OPSD %.8x %.8x NPSD %.8x %.8x SPDF5 %.8x DQE %x LMN %8s\n", TPSD[0], TPSD[1], PSD1, PSD2, SPAD[0xf5], dqe, n); @@ -6143,153 +6105,100 @@ sim_debug(DEBUG_IRQ, &cpu_dev, sim_debug(DEBUG_IRQ, &cpu_dev, " R4=%.8x R5=%.8x R6=%.8x R7=%.8x\n", GPR[4], GPR[5], GPR[6], GPR[7]); } -//210 cpu_dev.dctrl |= DEBUG_DETAIL; /* start instruction trace */ +// cpu_dev.dctrl |= DEBUG_DETAIL; /* start instruction trace */ } #endif - if (opr & 0x0200) { /* Was it LPSDCM? */ - /* map bit must be on to load maps */ - if (PSD2 & MAPBIT) { - /* set mapped mode in cpu status */ - CPUSTATUS |= BIT8; /* set bit 8 of cpu status */ -#ifdef NOT_NOW -// sim_debug(DEBUG_DETAIL, &cpu_dev, - sim_debug(DEBUG_IRQ, &cpu_dev, - "B4 LPSDCM temp %06x TPSD %08x %08x PSD %08x %08x\n", - temp, TPSD[0], TPSD[1], PSD1, PSD2); -// sim_debug(DEBUG_DETAIL, &cpu_dev, - sim_debug(DEBUG_IRQ, &cpu_dev, - "B4 LPSDCM BPIX %04x CPIX %04x CPIXPL %04x\n", - BPIX, CPIX, CPIXPL); -#endif - /* this mod fixes MPX 1.X 1st swapr load */ - /* any O/S or user maps yet? */ - if (((CPIX != 0) && (CPIXPL == 0)) && (PSD2 & RETMBIT)) { - PSD2 &= ~RETMBIT; /* no, turn off retain bit in PSD2 */ - sim_debug(DEBUG_EXP, &cpu_dev, "Turn off retain bit\n"); - } + if (opr & 0x0200) { /* Was it LPSDCM? */ + /* map bit must be on to load maps */ + if (PSD2 & MAPBIT) { + /* set mapped mode in cpu status */ + CPUSTATUS |= BIT8; /* set bit 8 of cpu status */ + /* this mod fixes MPX 1.X 1st swapr load */ + /* any O/S or user maps yet? */ + if (((CPIX != 0) && (CPIXPL == 0)) && (PSD2 & RETMBIT)) { + PSD2 &= ~RETMBIT; /* no, turn off retain bit in PSD2 */ + sim_debug(DEBUG_EXP, &cpu_dev, "Turn off retain bit\n"); + } - /* test if user count is equal to CPIXPL, if not load maps */ - /* this fixes software error in MPX3X where count is changed */ - /* but the retain bit was left set, so new maps were not loaded */ - /* until the next context switch and causes loading error */ - /* CHANGED 041420 maybe not right */ - if ((PSD2 & RETMBIT)) { /* don't load maps if retain bit set */ - uint32 mpl = SPAD[0xf3]; /* get mpl from spad address */ - uint32 cpix = PSD2 & 0x3ff8; /* get cpix 11 bit offset from psd wd 2 */ - uint32 midl = RMW(mpl+cpix); /* get midl entry for given user cpix */ - uint32 spc = midl & MASK16; /* get 16 bit user segment description count */ - if (spc != CPIXPL) { -#ifdef NOT_NOW -sim_debug(DEBUG_IRQ, &cpu_dev, -"LPSDCM RESET RETAIN OPSD %08x %08x NPSD %08x %08x TRAPME %02x spc %02x CPIXPL %03x\n", -TPSD[0], TPSD[1], PSD1, PSD2, TRAPME, spc, CPIXPL); -#endif + /* test if user count is equal to CPIXPL, if not load maps */ + /* this fixes software error in MPX3X where count is changed */ + /* but the retain bit was left set, so new maps were not loaded */ + /* until the next context switch and causes loading error */ + /* CHANGED 041420 maybe not right */ + if ((PSD2 & RETMBIT)) { /* don't load maps if retain bit set */ + uint32 mpl = SPAD[0xf3]; /* get mpl from spad address */ + uint32 cpix = PSD2 & 0x3ff8; /* get cpix 11 bit offset from psd wd 2 */ + uint32 midl = RMW(mpl+cpix); /* get midl entry for given user cpix */ + uint32 spc = midl & MASK16; /* get 16 bit user segment description count */ + if (spc != CPIXPL) { + PSD2 &= ~RETMBIT; /* no, turn off retain bit in PSD2 */ + } + else { + if ((CPU_MODEL == MODEL_67) || (CPU_MODEL == MODEL_97) || + (CPU_MODEL == MODEL_V6) || (CPU_MODEL == MODEL_V9)) { PSD2 &= ~RETMBIT; /* no, turn off retain bit in PSD2 */ } -#ifndef FIX4TLB - else { - if ((CPU_MODEL == MODEL_67) || (CPU_MODEL == MODEL_97) || - (CPU_MODEL == MODEL_V6) || (CPU_MODEL == MODEL_V9)) { -#ifdef NOT_NOW -sim_debug(DEBUG_IRQ, &cpu_dev, -"LPSDCM FORCE OFF RETAIN OPSD %08x %08x NPSD %08x %08x TRAPME %02x spc %02x CPIXPL %03x\n", -TPSD[0], TPSD[1], PSD1, PSD2, TRAPME, spc, CPIXPL); -#endif - PSD2 &= ~RETMBIT; /* no, turn off retain bit in PSD2 */ - } - } -#endif } + } - if ((PSD2 & RETMBIT) == 0) { /* don't load maps if retain bit set */ - /* we need to load the new maps */ - TRAPME = load_maps(PSD, 0); /* load maps for new PSD */ -#ifdef NOT_NOW -// sim_debug(DEBUG_DETAIL, &cpu_dev, - sim_debug(DEBUG_IRQ, &cpu_dev, - "AF LPSDCM TPSD %08x %08x PSD %08x %08x TRAPME %02x\n", - TPSD[0], TPSD[1], PSD1, PSD2, TRAPME); -// sim_debug(DEBUG_DETAIL, &cpu_dev, - sim_debug(DEBUG_IRQ, &cpu_dev, - "AF LPSDCM BPIX %04x CPIX %04x CPIXPL %04x\n", - BPIX, CPIX, CPIXPL); -// sim_debug(DEBUG_DETAIL, &cpu_dev, - sim_debug(DEBUG_IRQ, &cpu_dev, - "AF LPSDCM OS MAPC[0-5] %08x %08x %08x %08x %08x %08x\n", - MAPC[0], MAPC[1], MAPC[2], MAPC[3], MAPC[4], MAPC[5]); -// sim_debug(DEBUG_DETAIL, &cpu_dev, - sim_debug(DEBUG_IRQ, &cpu_dev, - "AF LPSDCM US MAPC[%x-%x] %08x %08x %08x %08x %08x %08x\n", - BPIX, BPIX+5, MAPC[BPIX], MAPC[BPIX+1], MAPC[BPIX+2], - MAPC[BPIX+3], MAPC[BPIX+4], MAPC[BPIX+5]); -#endif - } - PSD2 &= ~RETMBIT; /* turn off retain bit in PSD2 */ - SPAD[0xf5] = PSD2; /* save the current PSD2 */ - SPAD[0xf9] = CPUSTATUS; /* save the cpu status in SPAD */ - sim_debug(DEBUG_IRQ, &cpu_dev, - "LPSDCM MAPS LOADED TRAPME %02x PSD1 %08x PSD2 %08x BPIX %02x CPIXPL %02x\n", - TRAPME, PSD1, PSD2, BPIX, CPIXPL); - } - PSD2 &= ~RETMBIT; /* turn off retain bit in PSD2 */ - } else { - /* LPSD */ - /* if cpix is zero, copy cpix from PSD2 in SPAD[0xf5] */ - if ((PSD2 & 0x3ff8) == 0) { - PSD2 |= (SPAD[0xf5] & 0x3ff8); /* use new cpix */ + if ((PSD2 & RETMBIT) == 0) { /* don't load maps if retain bit set */ + /* we need to load the new maps */ + TRAPME = load_maps(PSD, 0); /* load maps for new PSD */ } + PSD2 &= ~RETMBIT; /* turn off retain bit in PSD2 */ + SPAD[0xf5] = PSD2; /* save the current PSD2 */ + SPAD[0xf9] = CPUSTATUS; /* save the cpu status in SPAD */ + sim_debug(DEBUG_IRQ, &cpu_dev, + "LPSDCM MAPS LOADED TRAPME %02x PSD1 %08x PSD2 %08x BPIX %02x CPIXPL %02x\n", + TRAPME, PSD1, PSD2, BPIX, CPIXPL); } -#ifdef NOT_NOW -sim_debug(DEBUG_IRQ, &cpu_dev, -"At LPSD(CM) OPSD %08x %08x NPSD %08x %08x TRAPME %02x\n", -TPSD[0], TPSD[1], PSD1, PSD2, TRAPME); -//210 cpu_dev.dctrl &= ~DEBUG_DETAIL; /* stop instruction trace */ -#endif - /* TRAPME can be error from LPSDCM or OK here */ - if (TRAPME) { /* if we have an error, restore old PSD */ - sim_debug(DEBUG_TRAP, &cpu_dev, + PSD2 &= ~RETMBIT; /* turn off retain bit in PSD2 */ + } else { + /* LPSD */ + /* if cpix is zero, copy cpix from PSD2 in SPAD[0xf5] */ + if ((PSD2 & 0x3ff8) == 0) { + PSD2 |= (SPAD[0xf5] & 0x3ff8); /* use new cpix */ + } + } + /* TRAPME can be error from LPSDCM or OK here */ + if (TRAPME) { /* if we have an error, restore old PSD */ + sim_debug(DEBUG_TRAP, &cpu_dev, "LPSDCM MAPS2 LOADED TRAPME = %02x PSD1 %08x PSD2 %08x CPUSTAT %08x SPAD[f9] %08x\n", - TRAPME, PSD1, PSD2, CPUSTATUS, SPAD[0xf9]); - PSD1 = TPSD[0]; /* restore PSD1 */ - /* HACK HACK HACK */ - /* Diags wants the new PSD2, not the original??? */ - /* if old one was used, we fail test 21/0 in cn.mmm for 32/67 */ -//DIAG PSD2 = TPSD[1]; /* restore PSD2 */ - CPUSTATUS = bc; /* restore the CPU STATUS */ - MODES = t; /* restore modes too */ - SPAD[0xf5] = ix; /* restore the current PSD2 to SPAD */ - SPAD[0xf9] = CPUSTATUS; /* save the cpu status in SPAD */ - irq_pend = reg; /* restore intr status */ - if ((CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9)) { - TRAPSTATUS |= BIT10; /* set bit 10 of trap status */ - TRAPSTATUS |= BIT7; /* set bit 7 of trap status */ - } else - TRAPSTATUS |= BIT18; /* set bit 18 of trap status */ - goto newpsd; /* go process error */ - } - drop_nop = 0; /* nothing to drop */ -#ifdef NOT_NOW - sim_debug(DEBUG_IRQ, &cpu_dev, - "LPSD(CM) END OPSD %08x %08x NPSD %08x %08x CPUSTAT %08x irq %1x BLK %1x\n", - TPSD[0], TPSD[1], PSD1, PSD2, CPUSTATUS, irq_pend, CPUSTATUS&0x80?1:0); -#endif - goto newpsd; /* load the new psd, or process error */ - break; - - case 0x4: /* JWCS */ /* not used in simulator */ - sim_debug(DEBUG_EXP, &cpu_dev, "Got JWCS\n"); - break; - case 0x2: /* BRI */ /* TODO - only for 32/55 or 32/7X in PSW mode */ - case 0x6: /* TRP */ - case 0x7: /* TPR */ - TRAPME = UNDEFINSTR_TRAP; /* trap condition */ - if ((CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9)) - TRAPSTATUS |= BIT0; /* set bit 0 of trap status */ - goto newpsd; /* undefined instruction trap */ - break; + TRAPME, PSD1, PSD2, CPUSTATUS, SPAD[0xf9]); + PSD1 = TPSD[0]; /* restore PSD1 */ + /* HACK HACK HACK */ + /* Diags wants the new PSD2, not the original??? */ + /* if old one was used, we fail test 21/0 in cn.mmm for 32/67 */ + CPUSTATUS = bc; /* restore the CPU STATUS */ + MODES = t; /* restore modes too */ + SPAD[0xf5] = ix; /* restore the current PSD2 to SPAD */ + SPAD[0xf9] = CPUSTATUS; /* save the cpu status in SPAD */ + irq_pend = reg; /* restore intr status */ + if ((CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9)) { + TRAPSTATUS |= BIT10; /* set bit 10 of trap status */ + TRAPSTATUS |= BIT7; /* set bit 7 of trap status */ + } else + TRAPSTATUS |= BIT18; /* set bit 18 of trap status */ + goto newpsd; /* go process error */ } + drop_nop = 0; /* nothing to drop */ + goto newpsd; /* load the new psd, or process error */ break; + case 0x4: /* JWCS */ /* not used in simulator */ + sim_debug(DEBUG_EXP, &cpu_dev, "Got JWCS\n"); + break; + case 0x2: /* BRI */ /* TODO - only for 32/55 or 32/7X in PSW mode */ + case 0x6: /* TRP */ + case 0x7: /* TPR */ + TRAPME = UNDEFINSTR_TRAP; /* trap condition */ + if ((CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9)) + TRAPSTATUS |= BIT0; /* set bit 0 of trap status */ + goto newpsd; /* undefined instruction trap */ + break; + } + break; + /* F Class I/O device instruction format */ /* |-----------+-----------+-----------+-----------+-----------+-----------+-----------+-----------| */ /* |00 01 02 03 04 05|06 07 08|09 10 11 12|13 14 15|16|17 18 19 20 21 22 23|24 25 26 27 28 29 30 31| */ @@ -6302,520 +6211,487 @@ TPSD[0], TPSD[1], PSD1, PSD2, TRAPME); /* | Op Code | Device Number | Aug | Command Code | */ /* |-----------+-----------+-----------+-----------+-----------+-----------+-----------+-----------| */ /* */ - case 0xFC>>2: /* 0xFC IMM - IMM */ /* XIO, CD, TD, Interrupt Control */ -/*0904*/ irq_pend = 1; /* start scanning interrupts again */ - if ((MODES & PRIVBIT) == 0) { /* must be privileged to do I/O */ -//sim_debug(DEBUG_EXP, &cpu_dev, "Privledged violation XIO\n"); - TRAPME = PRIVVIOL_TRAP; /* set the trap to take */ - if ((CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9)) - TRAPSTATUS |= BIT0; /* set bit 0 of trap status */ - else - TRAPSTATUS |= BIT19; /* set bit 19 of trap status */ - goto newpsd; /* Privlege violation trap */ + case 0xFC>>2: /* 0xFC IMM - IMM */ /* XIO, CD, TD, Interrupt Control */ + irq_pend = 1; /* start scanning interrupts again */ + if ((MODES & PRIVBIT) == 0) { /* must be privileged to do I/O */ + TRAPME = PRIVVIOL_TRAP; /* set the trap to take */ + if ((CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9)) + TRAPSTATUS |= BIT0; /* set bit 0 of trap status */ + else + TRAPSTATUS |= BIT19; /* set bit 19 of trap status */ + goto newpsd; /* Privlege violation trap */ + } + if ((opr & 0x7) != 0x07) { /* aug is 111 for XIO instruction */ + /* Process Non-XIO instructions */ + uint32 status = 0; /* status returned from device */ + uint32 device = (opr >> 3) & 0x7f; /* get device code */ + uint32 prior = device; /* interrupt priority */ + uint32 maxlev = 0x5f; /* max lev for all but 32/27 in diags */ +//MAYBEBAD uint32 maxlev = 0x6f; /* max lev for all but 32/27 in diags */ + + t = SPAD[prior+0x80]; /* get spad entry for interrupt */ + addr = SPAD[0xf1] + (prior<<2); /* vector address in SPAD */ + addr = M[addr>>2]; /* get the interrupt context block addr */ + prior = (opr >> 3) & 0x7f; /* get priority level */ + if (CPU_MODEL <= MODEL_27) { + maxlev = 0x6f; /* 27 uses 112 */ } - if ((opr & 0x7) != 0x07) { /* aug is 111 for XIO instruction */ - /* Process Non-XIO instructions */ - uint32 status = 0; /* status returned from device */ - uint32 device = (opr >> 3) & 0x7f; /* get device code */ - uint32 prior = device; /* interrupt priority */ - uint32 maxlev = 0x5f; /* max lev for all but 32/27 in diags */ -//TRYBAD uint32 maxlev = 0x6f; /* max lev for all but 32/27 in diags */ - t = SPAD[prior+0x80]; /* get spad entry for interrupt */ - addr = SPAD[0xf1] + (prior<<2); /* vector address in SPAD */ - addr = M[addr>>2]; /* get the interrupt context block addr */ - prior = (opr >> 3) & 0x7f; /* get priority level */ - if (CPU_MODEL <= MODEL_27) { - maxlev = 0x6f; /* 27 uses 112 */ + switch(opr & 0x7) { /* use bits 13-15 to determine instruction */ + case 0x0: /* EI FC00 Enable Interrupt */ + if (prior > maxlev) /* ignore for invalid levels */ + break; /* ignore */ + /* SPAD entries for interrupts begin at 0x80 */ + t = SPAD[prior+0x80]; /* get spad entry for interrupt */ + + if ((t == 0) || (t == 0xffffffff)) /* if unused, ignore instruction */ + break; /* ignore */ + + if ((t & 0x0f800000) == 0x0f000000) /* if class F ignore instruction */ + break; /* ignore for F class */ + + /* does not effect REQ status */ + INTS[prior] |= INTS_ENAB; /* enable specified int level */ + SPAD[prior+0x80] |= SINT_ENAB; /* enable in SPAD too */ + irq_pend = 1; /* start scanning interrupts again */ + + /* test for clock at address 0x7f06 and interrupt level 0x18 */ + /* the diags want the type to be 0 */ + /* UTX wants the type to be 3?? */ + /* UTX would be 0x03807f06 Diags would be 0x00807f06 */ + if ((SPAD[prior+0x80] & 0x0000ffff) == 0x00007f06) { + sim_debug(DEBUG_IRQ, &cpu_dev, + "Clock EI %02x SPAD %08x Turn on\n", prior, t); + rtc_setup(1, prior); /* tell clock to start */ } + /* the diags want the type to be 3 */ + if ((SPAD[prior+0x80] & 0x0f00ffff) == 0x03007f04) { + sim_debug(DEBUG_IRQ, &cpu_dev, + "Intv Timer EI %02x SPAD %08x Turn on\n", prior, t); + itm_setup(1, prior); /* tell timer to start */ + } + break; - switch(opr & 0x7) { /* use bits 13-15 to determine instruction */ - case 0x0: /* EI FC00 Enable Interrupt */ - if (prior > maxlev) /* ignore for invalid levels */ - break; /* ignore */ - /* SPAD entries for interrupts begin at 0x80 */ - t = SPAD[prior+0x80]; /* get spad entry for interrupt */ + case 0x1: /* DI FC01 */ + if (prior > maxlev) /* ignore for invalid levels */ + break; /* ignore */ + /* SPAD entries for interrupts begin at 0x80 */ + t = SPAD[prior+0x80]; /* get spad entry for interrupt */ - if ((t == 0) || (t == 0xffffffff)) /* if unused, ignore instruction */ - break; /* ignore */ - - if ((t & 0x0f800000) == 0x0f000000) /* if class F ignore instruction */ -// if ((t & 0x0f808000) == 0x0f000000) /* if class F ignore instruction */ - break; /* ignore for F class */ - -// sim_debug(DEBUG_IRQ, &cpu_dev, "EI:B4 %02x SPAD[%d] %08x ACT %1x REQ %1x ENAB %1x\n", -// prior, prior+0x80, t, INTS[prior]&INTS_ACT?1:0, -// INTS[prior]&INTS_REQ?1:0, INTS[prior]&INTS_ENAB?1:0); - - /* does not effect REQ status */ - INTS[prior] |= INTS_ENAB; /* enable specified int level */ - SPAD[prior+0x80] |= SINT_ENAB; /* enable in SPAD too */ - irq_pend = 1; /* start scanning interrupts again */ - - /* test for clock at address 0x7f06 and interrupt level 0x18 */ - /* the diags want the type to be 0 */ - /* UTX wants the type to be 3?? */ - /* UTX would be 0x03807f06 Diags would be 0x00807f06 */ - if ((SPAD[prior+0x80] & 0x0000ffff) == 0x00007f06) { - sim_debug(DEBUG_IRQ, &cpu_dev, - "Clock EI %02x SPAD %08x Turn on\n", prior, t); - rtc_setup(1, prior); /* tell clock to start */ - } - /* the diags want the type to be 3 */ - if ((SPAD[prior+0x80] & 0x0f00ffff) == 0x03007f04) { - sim_debug(DEBUG_IRQ, &cpu_dev, - "Intv Timer EI %02x SPAD %08x Turn on\n", prior, t); - itm_setup(1, prior); /* tell timer to start */ - } - break; - - case 0x1: /* DI FC01 */ - if (prior > maxlev) /* ignore for invalid levels */ - break; /* ignore */ - /* SPAD entries for interrupts begin at 0x80 */ - t = SPAD[prior+0x80]; /* get spad entry for interrupt */ - - if ((t == 0) || (t == 0xffffffff)) /* if unused, ignore instruction */ - break; /* ignore */ + if ((t == 0) || (t == 0xffffffff)) /* if unused, ignore instruction */ + break; /* ignore */ - if ((t & 0x0f800000) == 0x0f000000) /* if class F ignore instruction */ - break; /* ignore for F class */ + if ((t & 0x0f800000) == 0x0f000000) /* if class F ignore instruction */ + break; /* ignore for F class */ -// sim_debug(DEBUG_IRQ, &cpu_dev, "DI:B4 %02x SPAD[%d] %08x ACT %1x REQ %1x ENAB %1x\n", -// prior, prior+0x80, t, INTS[prior]&INTS_ACT?1:0, -// INTS[prior]&INTS_REQ?1:0, INTS[prior]&INTS_ENAB?1:0); + /* active state is left alone */ + INTS[prior] &= ~INTS_ENAB; /* disable specified int level */ + SPAD[prior+0x80] &= ~SINT_ENAB; /* disable in SPAD too */ + INTS[prior] &= ~INTS_REQ; /* clears any requests also */ + irq_pend = 1; /* start scanning interrupts again */ - /* active state is left alone */ - INTS[prior] &= ~INTS_ENAB; /* disable specified int level */ - SPAD[prior+0x80] &= ~SINT_ENAB; /* disable in SPAD too */ - INTS[prior] &= ~INTS_REQ; /* clears any requests also */ - irq_pend = 1; /* start scanning interrupts again */ + /* test for clock at address 0x7f06 and interrupt level 0x18 */ + /* the diags want the type to be 0 */ + /* UTX wants the type to be 3?? */ + /* UTX would be 0x03807f06 Diags would be 0x00807f06 */ + if ((SPAD[prior+0x80] & 0x0000ffff) == 0x00007f06) { + sim_debug(DEBUG_IRQ, &cpu_dev, + "Clock DI %02x SPAD %08x Turn off\n", prior, t); + rtc_setup(0, prior); /* tell clock to stop */ + } + /* the diags want the type to be 3 */ + if ((SPAD[prior+0x80] & 0x0f00ffff) == 0x03007f04) { + sim_debug(DEBUG_IRQ, &cpu_dev, + "Intv Timer DI %02x SPAD %08x Turn off\n", prior, t); + itm_setup(0, prior); /* tell timer to stop */ + } + break; - /* test for clock at address 0x7f06 and interrupt level 0x18 */ - /* the diags want the type to be 0 */ - /* UTX wants the type to be 3?? */ - /* UTX would be 0x03807f06 Diags would be 0x00807f06 */ - if ((SPAD[prior+0x80] & 0x0000ffff) == 0x00007f06) { - sim_debug(DEBUG_IRQ, &cpu_dev, - "Clock DI %02x SPAD %08x Turn off\n", prior, t); - rtc_setup(0, prior); /* tell clock to stop */ - } - /* the diags want the type to be 3 */ - if ((SPAD[prior+0x80] & 0x0f00ffff) == 0x03007f04) { - sim_debug(DEBUG_IRQ, &cpu_dev, - "Intv Timer DI %02x SPAD %08x Turn off\n", prior, t); - itm_setup(0, prior); /* tell timer to stop */ - } - break; - - case 0x2: /* RI FC02 */ - if (prior > maxlev) /* ignore for invalid levels */ - break; /* ignore */ - /* SPAD entries for interrupts begin at 0x80 */ - t = SPAD[prior+0x80]; /* get spad entry for interrupt */ + case 0x2: /* RI FC02 */ + if (prior > maxlev) /* ignore for invalid levels */ + break; /* ignore */ + /* SPAD entries for interrupts begin at 0x80 */ + t = SPAD[prior+0x80]; /* get spad entry for interrupt */ - if ((t == 0) || (t == 0xffffffff)) /* if unused, ignore instruction */ - break; /* ignore */ + if ((t == 0) || (t == 0xffffffff)) /* if unused, ignore instruction */ + break; /* ignore */ - if ((t & 0x0f800000) == 0x0f000000) /* if class F ignore instruction */ - break; /* ignore for F class */ + if ((t & 0x0f800000) == 0x0f000000) /* if class F ignore instruction */ + break; /* ignore for F class */ -// sim_debug(DEBUG_IRQ, &cpu_dev, "RI:B4 %02x SPAD[%d] %08x ACT %1x REQ %1x ENAB %1x\n", -// prior, prior+0x80, t, INTS[prior]&INTS_ACT?1:0, -// INTS[prior]&INTS_REQ?1:0, INTS[prior]&INTS_ENAB?1:0); + INTS[prior] |= INTS_REQ; /* set the request flag for this level */ + irq_pend = 1; /* start scanning interrupts again */ + break; - INTS[prior] |= INTS_REQ; /* set the request flag for this level */ - irq_pend = 1; /* start scanning interrupts again */ - break; - - case 0x3: /* AI FC03 */ - if (prior > maxlev) /* ignore for invalid levels */ - break; /* ignore */ - /* SPAD entries for interrupts begin at 0x80 */ - t = SPAD[prior+0x80]; /* get spad entry for interrupt */ + case 0x3: /* AI FC03 */ + if (prior > maxlev) /* ignore for invalid levels */ + break; /* ignore */ + /* SPAD entries for interrupts begin at 0x80 */ + t = SPAD[prior+0x80]; /* get spad entry for interrupt */ - if ((t == 0) || (t == 0xffffffff)) /* if unused, ignore instruction */ - break; /* ignore */ + if ((t == 0) || (t == 0xffffffff)) /* if unused, ignore instruction */ + break; /* ignore */ - if ((t & 0x0f800000) == 0x0f000000) /* if class F ignore instruction */ - break; /* ignore for F class */ + if ((t & 0x0f800000) == 0x0f000000) /* if class F ignore instruction */ + break; /* ignore for F class */ -// sim_debug(DEBUG_IRQ, &cpu_dev, "AI:B4 %02x SPAD[%d] %08x ACT %1x REQ %1x ENAB %1x\n", -// prior, prior+0x80, t, INTS[prior]&INTS_ACT?1:0, -// INTS[prior]&INTS_REQ?1:0, INTS[prior]&INTS_ENAB?1:0); + INTS[prior] |= INTS_ACT; /* activate specified int level */ + SPAD[prior+0x80] |= SINT_ACT; /* activate in SPAD too */ + irq_pend = 1; /* start scanning interrupts again */ + break; - INTS[prior] |= INTS_ACT; /* activate specified int level */ - SPAD[prior+0x80] |= SINT_ACT; /* activate in SPAD too */ - irq_pend = 1; /* start scanning interrupts again */ - break; - - case 0x4: /* DAI FC04 */ - if (prior > maxlev) /* ignore for invalid levels */ - break; /* ignore */ - /* SPAD entries for interrupts begin at 0x80 */ - t = SPAD[prior+0x80]; /* get spad entry for interrupt */ + case 0x4: /* DAI FC04 */ + if (prior > maxlev) /* ignore for invalid levels */ + break; /* ignore */ + /* SPAD entries for interrupts begin at 0x80 */ + t = SPAD[prior+0x80]; /* get spad entry for interrupt */ - if ((t == 0) || (t == 0xffffffff)) /* if unused, ignore instruction */ - break; /* ignore */ + if ((t == 0) || (t == 0xffffffff)) /* if unused, ignore instruction */ + break; /* ignore */ - if ((t & 0x0f800000) == 0x0f000000) /* if class F ignore instruction */ - break; /* ignore for F class */ + if ((t & 0x0f800000) == 0x0f000000) /* if class F ignore instruction */ + break; /* ignore for F class */ -// sim_debug(DEBUG_IRQ, &cpu_dev, "DAI:B4 %02x SPAD[%d] %08x ACT %1x REQ %1x ENAB %1x\n", -// prior, prior+0x80, t, INTS[prior]&INTS_ACT?1:0, -// INTS[prior]&INTS_REQ?1:0, INTS[prior]&INTS_ENAB?1:0); + INTS[prior] &= ~INTS_ACT; /* deactivate specified int level */ + SPAD[prior+0x80] &= ~SINT_ACT; /* deactivate in SPAD too */ + irq_pend = 1; /* start scanning interrupts again */ + /* instruction following a DAI can not be interrupted */ + /* skip tests for interrupts if this is the case */ + skipinstr = 1; /* skip interrupt test */ + break; - INTS[prior] &= ~INTS_ACT; /* deactivate specified int level */ - SPAD[prior+0x80] &= ~SINT_ACT; /* deactivate in SPAD too */ - irq_pend = 1; /* start scanning interrupts again */ - /* instruction following a DAI can not be interrupted */ - /* skip tests for interrupts if this is the case */ -#ifdef NOTNOW - sim_debug(DEBUG_IRQ, &cpu_dev, - "DAI lev %02x Skipinstr %1x set PSD1 %08x PSD2 %08x CPUSTATUS %08x\n", - prior, skipinstr, PSD1, PSD2, CPUSTATUS); -#endif - skipinstr = 1; /* skip interrupt test */ - break; - - case 0x5: /* TD FC05 */ /* bits 13-15 is test code type */ - case 0x6: /* CD FC06 */ - /* If CD or TD, make sure device is not F class device */ - /* the channel must be defined as a non class F I/O channel in SPAD */ - /* if class F, the system will generate a system check trap */ - t = SPAD[device]; /* get spad entry for channel */ - if ((t & 0x0f000000) == 0x0f000000) { /* class in bits 4-7 */ - TRAPME = SYSTEMCHK_TRAP; /* trap condition if F class */ - TRAPSTATUS &= ~BIT0; /* class E error bit */ - TRAPSTATUS &= ~BIT1; /* I/O processing error */ - goto newpsd; /* machine check trap */ - } - /* t has spad entry for device */ - /* get the 1's comp of interrupt address from bits 9-15 SPAD entry */ - ix = ((~t)>>16)&0x7f; /* get positive number for interrupt */ - if (opr & 0x1) { /* see if CD or TD */ - /* TODO process a TD */ - if (device == 0x7f) { - /* if this is for the interval timer check cmd type */ - /* if TD 8000 or 4000, set all cc's zero */ - temp = (IR & 0xf000); /* get cmd from instruction */ - if ((temp == 0x4000) || (temp == 0x8000)) - status = 0; /* no CC's */ - else + case 0x5: /* TD FC05 */ /* bits 13-15 is test code type */ + case 0x6: /* CD FC06 */ + /* If CD or TD, make sure device is not F class device */ + /* the channel must be defined as a non class F I/O channel in SPAD */ + /* if class F, the system will generate a system check trap */ + t = SPAD[device]; /* get spad entry for channel */ + if ((t & 0x0f000000) == 0x0f000000) { /* class in bits 4-7 */ + TRAPME = SYSTEMCHK_TRAP; /* trap condition if F class */ + TRAPSTATUS &= ~BIT0; /* class E error bit */ + TRAPSTATUS &= ~BIT1; /* I/O processing error */ + goto newpsd; /* machine check trap */ + } + /* t has spad entry for device */ + /* get the 1's comp of interrupt address from bits 9-15 SPAD entry */ + ix = ((~t)>>16)&0x7f; /* get positive number for interrupt */ + if (opr & 0x1) { /* see if CD or TD */ + /* TODO process a TD */ + if (device == 0x7f) { + /* if this is for the interval timer check cmd type */ + /* if TD 8000 or 4000, set all cc's zero */ + temp = (IR & 0xf000); /* get cmd from instruction */ + if ((temp == 0x4000) || (temp == 0x8000)) + status = 0; /* no CC's */ + else /* if TD 2000 set CC2 for caller */ if (temp == 0x2000) status = CC2BIT; /* set CC2 */ - /* return status has new CC's in bits 1-4 of status word */ - /* insert status CCs */ - PSD1 = ((PSD1 & 0x87fffffe) | (status & 0x78000000)); - } else { - /* may want to handle class E someday */ -// if ((TRAPME = testEIO(device, testcode, &status))) -// goto newpsd; /* error returned, trap cpu */ - /* return status has new CC's in bits 1-4 of status word */ -// /* insert status CCs */ -// PSD1 = ((PSD1 & 0x87fffffe) | (status & 0x78000000)); - goto inv; /* invalid instruction until I fix it */ - } + /* return status has new CC's in bits 1-4 of status word */ + /* insert status CCs */ + PSD1 = ((PSD1 & 0x87fffffe) | (status & 0x78000000)); } else { - /* TODO process a CD */ -// if ((TRAPME = startEIO(device, &status))) -// goto newpsd; /* error returned, trap cpu */ - if (device == 0x7f) { - temp = (IR & 0x7f); /* get cmd from instruction */ - status = itm_rdwr(temp, GPR[0], ix); /* read/write the interval timer */ - /* see if the cmd does not return value */ - /* if bit 25 set, read reg val into R0 */ - if (temp & 0x40) - GPR[0] = status; /* return count in reg 0 */ - /* No CC's going out */ - } else { - goto inv; /* invalid instruction until I fix it */ - } + /* may want to handle class E someday */ +// if ((TRAPME = testEIO(device, testcode, &status))) +// goto newpsd; /* error returned, trap cpu */ + /* return status has new CC's in bits 1-4 of status word */ +// /* insert status CCs */ +// PSD1 = ((PSD1 & 0x87fffffe) | (status & 0x78000000)); + goto inv; /* invalid instruction until I fix it */ + } + } else { + /* TODO process a CD */ +// if ((TRAPME = startEIO(device, &status))) +// goto newpsd; /* error returned, trap cpu */ + if (device == 0x7f) { + temp = (IR & 0x7f); /* get cmd from instruction */ + status = itm_rdwr(temp, GPR[0], ix); /* read/write the interval timer */ + /* see if the cmd does not return value */ + /* if bit 25 set, read reg val into R0 */ + if (temp & 0x40) + GPR[0] = status; /* return count in reg 0 */ + /* No CC's going out */ + } else { + goto inv; /* invalid instruction until I fix it */ } - break; - case 0x7: /* XIO FC07*/ /* should never get here */ - break; } - break; /* skip over XIO code */ + break; + case 0x7: /* XIO FC07*/ /* should never get here */ + break; } + break; /* skip over XIO code */ + } - /* Process XIO instructions */ - /* see if valid instruction */ - /* DIAGS wants this tested first */ - switch((opr >> 3) & 0xf) { /* use bits 9-12 to determine I/O instruction */ - case 0x00: /* Unassigned */ - case 0x01: /* Unassigned */ - case 0x0A: /* Unassigned */ - TRAPME = UNDEFINSTR_TRAP; /* trap condition */ - if ((CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9)) - TRAPSTATUS |= BIT0; /* set bit 0 of trap status */ - goto newpsd; /* undefined instruction trap */ - } + /* Process XIO instructions */ + /* see if valid instruction */ + /* DIAGS wants this tested first */ + switch((opr >> 3) & 0xf) { /* use bits 9-12 to determine I/O instruction */ + case 0x00: /* Unassigned */ + case 0x01: /* Unassigned */ + case 0x0A: /* Unassigned */ + TRAPME = UNDEFINSTR_TRAP; /* trap condition */ + if ((CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9)) + TRAPSTATUS |= BIT0; /* set bit 0 of trap status */ + goto newpsd; /* undefined instruction trap */ + } - /* if reg is non-zero, add reg to 15 bits from instruction */ - if (reg) - temp2 = (IR & 0x7fff) + (GPR[reg] & 0x7fff); /* set new chan/suba into IR */ - else - temp2 = (IR & 0x7fff); /* set new chan/suba into IR */ - lchan = (temp2 & 0x7F00) >> 8; /* get 7 bit logical channel address */ - suba = temp2 & 0xFF; /* get 8 bit subaddress */ - lchsa = (lchan << 8) | suba; /* logical address */ - /* the channel must be defined as a class F I/O channel in SPAD */ - /* if not class F, the system will generate a system check trap */ - t = SPAD[lchan]; /* get spad entry for channel */ - if ((t == 0 || t == 0xffffffff) || /* if not set up, system check */ - ((t & 0x0f800000) != 0x0f000000)) { /* class in bits 4-7 */ -// sim_debug(DEBUG_XIO, &cpu_dev, -// "$$ XIO SYSTEMCHK lchan %04x sa %04x spad %08x BLK %1x INTS[%02x] %08x\n", -// lchan, suba, t, CPUSTATUS&0x80?1:0, ix, INTS[ix]); -// sim_debug(DEBUG_XIO, &cpu_dev, -// "$$ XIO SYSTEMCHK2 IR %08x temp2 %04x lchsa %04x opr %02x GPR[%02x] %08x\n", -// IR, temp2, lchsa, (opr>>3)&0xf, reg, GPR[reg]); - TRAPME = SYSTEMCHK_TRAP; /* trap condition if F class */ - TRAPSTATUS |= BIT0; /* class F error bit */ - TRAPSTATUS &= ~BIT1; /* I/O processing error */ - goto newpsd; /* undefined instruction trap */ - } - /* get real channel from spad device entry */ - chan = (t & 0x7f00) >> 8; /* real channel */ - rchsa = (chan << 8) | suba; /* real ch & sa */ - /* get the 1's comp of interrupt address from bits 9-15 SPAD entry */ - ix = ((~t)>>16)&0x7f; /* get positive number for interrupt */ - bc = SPAD[ix+0x80]; /* get interrupt spad entry for channel */ - /* SPAD address F1 has interrupt table address */ - temp = SPAD[0xf1] + (ix<<2); /* vector address in SPAD */ - sim_debug(DEBUG_XIO, &cpu_dev, - "$$ XIO lchan %02x sa %02x spad %08x BLK %1x INTS[%02x] %08x\n", - lchan, suba, t, CPUSTATUS&0x80?1:0, ix, INTS[ix]); - sim_debug(DEBUG_XIO, &cpu_dev, - "$$ XIO rchsa %04x PSD1 %08x PSD2 %08x IR %08x ICBA %06x\n", - rchsa, PSD1, PSD2, IR, temp); - if ((TRAPME = Mem_read(temp, &addr))) { /* get interrupt context block addr */ + /* if reg is non-zero, add reg to 15 bits from instruction */ + if (reg) + temp2 = (IR & 0x7fff) + (GPR[reg] & 0x7fff); /* set new chan/suba into IR */ + else + temp2 = (IR & 0x7fff); /* set new chan/suba into IR */ + lchan = (temp2 & 0x7F00) >> 8; /* get 7 bit logical channel address */ + suba = temp2 & 0xFF; /* get 8 bit subaddress */ + lchsa = (lchan << 8) | suba; /* logical address */ + /* the channel must be defined as a class F I/O channel in SPAD */ + /* if not class F, the system will generate a system check trap */ + t = SPAD[lchan]; /* get spad entry for channel */ + if ((t == 0 || t == 0xffffffff) || /* if not set up, system check */ + ((t & 0x0f800000) != 0x0f000000)) { /* class in bits 4-7 */ + TRAPME = SYSTEMCHK_TRAP; /* trap condition if F class */ + TRAPSTATUS |= BIT0; /* class F error bit */ + TRAPSTATUS &= ~BIT1; /* I/O processing error */ + goto newpsd; /* undefined instruction trap */ + } + /* get real channel from spad device entry */ + chan = (t & 0x7f00) >> 8; /* real channel */ + rchsa = (chan << 8) | suba; /* real ch & sa */ + /* get the 1's comp of interrupt address from bits 9-15 SPAD entry */ + ix = ((~t)>>16)&0x7f; /* get positive number for interrupt */ + bc = SPAD[ix+0x80]; /* get interrupt spad entry for channel */ + /* SPAD address F1 has interrupt table address */ + temp = SPAD[0xf1] + (ix<<2); /* vector address in SPAD */ + sim_debug(DEBUG_XIO, &cpu_dev, + "$$ XIO lchan %02x sa %02x spad %08x BLK %1x INTS[%02x] %08x\n", + lchan, suba, t, CPUSTATUS&0x80?1:0, ix, INTS[ix]); + sim_debug(DEBUG_XIO, &cpu_dev, + "$$ XIO rchsa %04x PSD1 %08x PSD2 %08x IR %08x ICBA %06x\n", + rchsa, PSD1, PSD2, IR, temp); + if ((TRAPME = Mem_read(temp, &addr))) { /* get interrupt context block addr */ mcheck: - /* machine check if not there */ - TRAPME = MACHINECHK_TRAP; /* trap condition */ - TRAPSTATUS |= BIT0; /* class F error bit */ - TRAPSTATUS &= ~BIT1; /* I/O processing error */ - goto newpsd; /* machine check trap */ - } - /* the context block contains the old PSD, */ - /* new PSD, IOCL address, and I/O status address */ - if ((addr == 0) || (addr == 0xffffffff)) { /* must be initialized address */ - goto mcheck; /* bad int icb address */ - } - if ((TRAPME = Mem_read(addr+16, &temp))) { /* get iocl address from icb wd 4 */ - goto mcheck; /* machine check if not there */ - } - /* iocla must be valid addr if it is a SIO instruction */ - if (((temp & MASK24) == 0) && (((opr >> 2) & 0xf) == 2)) { - goto mcheck; /* bad iocl address */ - } + /* machine check if not there */ + TRAPME = MACHINECHK_TRAP; /* trap condition */ + TRAPSTATUS |= BIT0; /* class F error bit */ + TRAPSTATUS &= ~BIT1; /* I/O processing error */ + goto newpsd; /* machine check trap */ + } + /* the context block contains the old PSD, */ + /* new PSD, IOCL address, and I/O status address */ + if ((addr == 0) || (addr == 0xffffffff)) { /* must be initialized address */ + goto mcheck; /* bad int icb address */ + } + if ((TRAPME = Mem_read(addr+16, &temp))) { /* get iocl address from icb wd 4 */ + goto mcheck; /* machine check if not there */ + } + /* iocla must be valid addr if it is a SIO instruction */ + if (((temp & MASK24) == 0) && (((opr >> 2) & 0xf) == 2)) { + goto mcheck; /* bad iocl address */ + } - sim_debug(DEBUG_XIO, &cpu_dev, - "XIO rdy PSD1 %08x chan %02x irq %02x icb %06x iocla %06x iocd %08x %08x\n", - PSD1, chan, ix, addr, addr+16, RMW(temp), RMW(temp+4)); - /* at this point, the channel has a valid SPAD channel entry */ - /* t is SPAD entry contents for chan device */ - /* temp2 has logical channel address */ - /* lchan - logical channel address */ - /* lchsa - logical channel & subaddress */ - /* chan - channel address */ - /* suba - channel device subaddress */ - /* rchsa - real chan & sub address from spad for logical channel */ - /* ix - positive interrupt level */ - /* addr - ICBA for specified interrupt level, points to 6 wd block */ - /* temp - First IOCD address */ - sim_debug(DEBUG_XIO, &cpu_dev, - "XIO switch %02x lchan %02x irq %02x rchsa %04x IOCDa %08x CPUSTATUS %08x BLK %1x\n", - ((opr>>3)&0x0f), lchan, ix, rchsa, temp, CPUSTATUS, CPUSTATUS&0x80?1:0); + sim_debug(DEBUG_XIO, &cpu_dev, + "XIO rdy PSD1 %08x chan %02x irq %02x icb %06x iocla %06x iocd %08x %08x\n", + PSD1, chan, ix, addr, addr+16, RMW(temp), RMW(temp+4)); + /* at this point, the channel has a valid SPAD channel entry */ + /* t is SPAD entry contents for chan device */ + /* temp2 has logical channel address */ + /* lchan - logical channel address */ + /* lchsa - logical channel & subaddress */ + /* chan - channel address */ + /* suba - channel device subaddress */ + /* rchsa - real chan & sub address from spad for logical channel */ + /* ix - positive interrupt level */ + /* addr - ICBA for specified interrupt level, points to 6 wd block */ + /* temp - First IOCD address */ + sim_debug(DEBUG_XIO, &cpu_dev, + "XIO switch %02x lchan %02x irq %02x rchsa %04x IOCDa %08x CPUSTATUS %08x BLK %1x\n", + ((opr>>3)&0x0f), lchan, ix, rchsa, temp, CPUSTATUS, CPUSTATUS&0x80?1:0); - switch((opr >> 3) & 0xf) { /* use bits 9-12 to determine I/O instruction */ - case 0x00: /* Unassigned */ - case 0x01: /* Unassigned */ - case 0x0A: /* Unassigned */ - TRAPME = UNDEFINSTR_TRAP; /* trap condition */ - if ((CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9)) - TRAPSTATUS |= BIT0; /* set bit 0 of trap status */ - goto newpsd; /* undefined instruction trap */ - break; - - case 0x09: /* Enable write channel ECWCS */ - case 0x0B: /* Write channel WCS WCWCS */ - /* TODO, provide support code */ - /* for now or maybe forever, return unsupported transaction */ - PSD1 = ((PSD1 & 0x87fffffe) | (CC2BIT|CC4BIT)); /* insert status 5 */ - sim_debug(DEBUG_XIO, &cpu_dev, - "XIO unsupported WCS chan %04x chsa %04x status %08x\n", - chan, rchsa, rstatus); - /* just give unsupported transaction */ -#ifdef JUST_RETURN_STATUS - TRAPME = SYSTEMCHK_TRAP; /* trap condition if F class */ - TRAPSTATUS |= BIT0; /* class F error bit */ - TRAPSTATUS &= ~BIT1; /* I/O processing error */ - goto newpsd; /* undefined instruction trap */ -#endif - break; - - case 0x02: /* Start I/O SIO */ - sim_debug(DEBUG_XIO, &cpu_dev, - "SIO b4 call PSD1 %08x rchsa %04x lchsa %04x BLK %1x\n", - PSD1, rchsa, lchsa, CPUSTATUS&0x80?1:0); - if ((TRAPME = startxio(lchsa, &rstatus))) - goto newpsd; /* error returned, trap cpu */ - PSD1 = ((PSD1 & 0x87fffffe) | (rstatus & 0x78000000)); /* insert status */ - sim_debug(DEBUG_XIO, &cpu_dev, - "SIO ret PSD1 %08x chan %04x chsa %04x status %08x BLK %1x\n", - PSD1, rchsa, lchsa, rstatus, CPUSTATUS&0x80?1:0); - break; - - case 0x03: /* Test I/O TIO */ - if ((TRAPME = testxio(lchsa, &rstatus))) { - sim_debug(DEBUG_TRAP, &cpu_dev, - "TIO ret PSD1 %x rchsa %x lchsa %x status %x BLK %1x\n", - PSD1, rchsa, lchsa, rstatus, CPUSTATUS&0x80?1:0); - goto newpsd; /* error returned, trap cpu */ - } - PSD1 = ((PSD1 & 0x87fffffe) | (rstatus & 0x78000000)); /* insert status */ - sim_debug(DEBUG_XIO, &cpu_dev, - "TIO ret PSD1 %08x lchsa %04x stat %08x spad %08x INTS[%02x] %08x BLK %1x\n", - PSD1, lchsa, rstatus, t, ix, INTS[ix], CPUSTATUS&0x80?1:0); - break; - - case 0x04: /* Stop I/O STPIO */ - if ((TRAPME = stopxio(lchsa, &rstatus))) - goto newpsd; /* error returned, trap cpu */ - PSD1 = ((PSD1 & 0x87fffffe) | (rstatus & 0x78000000)); /* insert status */ - sim_debug(DEBUG_XIO, &cpu_dev, "STPIO ret rchsa %04x lchsa %04x status %08x\n", - rchsa, lchsa, rstatus); - break; - - case 0x05: /* Reset channel RSCHNL */ - if ((TRAPME = rschnlxio(lchsa, &rstatus))) - goto newpsd; /* error returned, trap cpu */ - /* SPAD entries for interrupts begin at 0x80 */ - INTS[ix] &= ~INTS_REQ; /* clears any requests */ - INTS[ix] &= ~INTS_ACT; /* deactivate specified int level */ - SPAD[ix+0x80] &= ~SINT_ACT; /* deactivate in SPAD too */ - PSD1 = ((PSD1 & 0x87fffffe) | (rstatus & 0x78000000)); /* insert status */ - sim_debug(DEBUG_XIO, &cpu_dev, "RSCHNL rschnlxio ret rchsa %04x lchsa %04x status %08x\n", - rchsa, lchsa, rstatus); - break; - - case 0x06: /* Halt I/O HIO */ - if ((TRAPME = haltxio(lchsa, &rstatus))) - goto newpsd; /* error returned, trap cpu */ - PSD1 = ((PSD1 & 0x87fffffe) | (rstatus & 0x78000000)); /* insert status */ - sim_debug(DEBUG_XIO, &cpu_dev, - "HIO haltxio ret rchsa %04x lchsa %04x status %08x\n", - rchsa, lchsa, rstatus); - break; - - case 0x07: /* Grab controller GRIO n/u */ - if ((TRAPME = grabxio(lchsa, &rstatus))) - goto newpsd; /* error returned, trap cpu */ - PSD1 = ((PSD1 & 0x87fffffe) | (rstatus & 0x78000000)); /* insert status */ - sim_debug(DEBUG_XIO, &cpu_dev, "GRIO ret rchsa %04x lchsa %04x status %08x\n", - rchsa, lchsa, rstatus); - break; - - case 0x08: /* Reset controller RSCTL */ - if ((TRAPME = rsctlxio(lchsa, &rstatus))) - goto newpsd; /* error returned, trap cpu */ - PSD1 = ((PSD1 & 0x87fffffe) | (rstatus & 0x78000000)); /* insert status */ - sim_debug(DEBUG_XIO, &cpu_dev, "RSCTL ret rchsa %04x lchsa %04x status %08x\n", - rchsa, lchsa, rstatus); - break; - - case 0x0C: /* Enable channel interrupt ECI */ - /* disable int only */ - sim_debug(DEBUG_XIO, &cpu_dev, - "ECI chsa %04x lchsa %04x spad %08x INTS[%02x] %08x\n", - rchsa, lchsa, t, ix, INTS[ix]); - - if ((TRAPME = checkxio(lchsa, &rstatus))) - goto newpsd; /* error returned, trap cpu */ - sim_debug(DEBUG_XIO, &cpu_dev, - "ECI after checkxio rchsa %04x suba %04x status %08x\n", - rchsa, suba, rstatus); - - if ((INTS[ix] & INTS_ACT) == 0) - sim_debug(DEBUG_XIO, &cpu_dev, - "ECI INT %02x is NOT set rchsa %04x lchsa %04x status %08x\n", - ix, rchsa, lchsa, rstatus); - /* SPAD entries for interrupts begin at 0x80 */ - INTS[ix] |= INTS_ENAB; /* enable specified int level */ - SPAD[ix+0x80] |= SINT_ENAB; /* enable in SPAD too */ - irq_pend = 1; /* start scanning interrupts again */ - /* return status of zero for present and functioning */ - PSD1 = ((PSD1 & 0x87fffffe) | (rstatus & 0x78000000)); /* insert status */ - break; - - case 0x0D: /* Disable channel interrupt DCI */ - /* disable int, leave req */ - sim_debug(DEBUG_XIO, &cpu_dev, - "DCI rchsa %04x lchsa %04x spad %08x INTS[%02x] %08x\n", - rchsa, lchsa, t, ix, INTS[ix]); - - if ((TRAPME = checkxio(lchsa, &rstatus))) - goto newpsd; /* error returned, trap cpu */ - sim_debug(DEBUG_XIO, &cpu_dev, - "DCI After checkxio call rstatus %08x\n", rstatus); - /* doc says we need to drop 1 queued status entry too */ - if ((INTS[ix] & INTS_ACT) == 0) - sim_debug(DEBUG_XIO, &cpu_dev, - "DCI INT %02x is NOT set rchsa %04x lchsa %04x status %08x\n", - ix, rchsa, lchsa, rstatus); - /* SPAD entries for interrupts begin at 0x80 */ - INTS[ix] &= ~INTS_ENAB; /* disable specified int level */ - SPAD[ix+0x80] &= ~SINT_ENAB; /* disable in SPAD too */ - PSD1 = ((PSD1 & 0x87fffffe) | (rstatus & 0x78000000)); /* insert status */ - break; - - case 0x0E: /* Activate channel interrupt ACI */ - /* Set int active, clear request */ - sim_debug(DEBUG_XIO, &cpu_dev, - "ACI rchsa %04x lchsa %04x spad %08x INTS[%02x] %08x\n", - rchsa, lchsa, t, ix, INTS[ix]); - - if ((TRAPME = checkxio(lchsa, &rstatus))) - goto newpsd; /* error returned, trap cpu */ - if ((INTS[ix] & INTS_ACT) == 0) - sim_debug(DEBUG_XIO, &cpu_dev, - "ACI INT %02x is NOT set rchsa %04x lchsa %04x status %08x\n", - ix, rchsa, lchsa, rstatus); - /* SPAD entries for interrupts begin at 0x80 */ - INTS[ix] |= INTS_ACT; /* activate specified int level */ - SPAD[ix+0x80] |= SINT_ACT; /* enable in SPAD too */ - PSD1 = ((PSD1 & 0x87fffffe) | (rstatus & 0x78000000)); /* insert status */ - break; - - case 0x0F: /* Deactivate channel interrupt DACI */ - /* Clear active and leave any request */ - /* Note, instruction following DACI is not interruptable */ - sim_debug(DEBUG_XIO, &cpu_dev, - "DACI rchsa %04x lchsa %04x spad %08x INTS[%02x] %08x\n", - rchsa, lchsa, t, ix, INTS[ix]); - - if ((TRAPME = checkxio(rchsa, &rstatus))) - goto newpsd; /* error returned, trap cpu */ - if ((INTS[ix] & INTS_ACT) == 0) - sim_debug(DEBUG_XIO, &cpu_dev, - "DACI INT %02x is NOT set chan %04x suba %04x status %08x\n", - ix, chan, suba, rstatus); - /* SPAD entries for interrupts begin at 0x80 */ - INTS[ix] &= ~INTS_ACT; /* deactivate specified int level */ - SPAD[ix+0x80] &= ~SINT_ACT; /* deactivate in SPAD too */ - irq_pend = 1; /* start scanning interrupts again */ - skipinstr = 1; /* skip interrupt test */ - PSD1 = ((PSD1 & 0x87fffffe) | (rstatus & 0x78000000)); /* insert status */ - sim_debug(DEBUG_XIO, &cpu_dev, - "DACI ret lchsa %04x status %08x spad %08x INTS[%02x] %08x BLK %1x\n", - lchsa, rstatus, t, ix, INTS[ix], CPUSTATUS&0x80?1:0); - break; - } /* end of XIO switch */ + switch((opr >> 3) & 0xf) { /* use bits 9-12 to determine I/O instruction */ + case 0x00: /* Unassigned */ + case 0x01: /* Unassigned */ + case 0x0A: /* Unassigned */ + TRAPME = UNDEFINSTR_TRAP; /* trap condition */ + if ((CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9)) + TRAPSTATUS |= BIT0; /* set bit 0 of trap status */ + goto newpsd; /* undefined instruction trap */ break; - } /* End of Instruction Switch */ + + case 0x09: /* Enable write channel ECWCS */ + case 0x0B: /* Write channel WCS WCWCS */ + /* TODO, provide support code */ + /* for now or maybe forever, return unsupported transaction */ + PSD1 = ((PSD1 & 0x87fffffe) | (CC2BIT|CC4BIT)); /* insert status 5 */ + sim_debug(DEBUG_XIO, &cpu_dev, + "XIO unsupported WCS chan %04x chsa %04x status %08x\n", + chan, rchsa, rstatus); + /* just give unsupported transaction */ +#ifdef JUST_RETURN_STATUS + TRAPME = SYSTEMCHK_TRAP; /* trap condition if F class */ + TRAPSTATUS |= BIT0; /* class F error bit */ + TRAPSTATUS &= ~BIT1; /* I/O processing error */ + goto newpsd; /* undefined instruction trap */ +#endif + break; + + case 0x02: /* Start I/O SIO */ + sim_debug(DEBUG_XIO, &cpu_dev, + "SIO b4 call PSD1 %08x rchsa %04x lchsa %04x BLK %1x\n", + PSD1, rchsa, lchsa, CPUSTATUS&0x80?1:0); + if ((TRAPME = startxio(lchsa, &rstatus))) + goto newpsd; /* error returned, trap cpu */ + PSD1 = ((PSD1 & 0x87fffffe) | (rstatus & 0x78000000)); /* insert status */ + sim_debug(DEBUG_XIO, &cpu_dev, + "SIO ret PSD1 %08x chan %04x chsa %04x status %08x BLK %1x\n", + PSD1, rchsa, lchsa, rstatus, CPUSTATUS&0x80?1:0); + break; + + case 0x03: /* Test I/O TIO */ + if ((TRAPME = testxio(lchsa, &rstatus))) { + sim_debug(DEBUG_TRAP, &cpu_dev, + "TIO ret PSD1 %x rchsa %x lchsa %x status %x BLK %1x\n", + PSD1, rchsa, lchsa, rstatus, CPUSTATUS&0x80?1:0); + goto newpsd; /* error returned, trap cpu */ + } + PSD1 = ((PSD1 & 0x87fffffe) | (rstatus & 0x78000000)); /* insert status */ + sim_debug(DEBUG_XIO, &cpu_dev, + "TIO ret PSD1 %08x lchsa %04x stat %08x spad %08x INTS[%02x] %08x BLK %1x\n", + PSD1, lchsa, rstatus, t, ix, INTS[ix], CPUSTATUS&0x80?1:0); + break; + + case 0x04: /* Stop I/O STPIO */ + if ((TRAPME = stopxio(lchsa, &rstatus))) + goto newpsd; /* error returned, trap cpu */ + PSD1 = ((PSD1 & 0x87fffffe) | (rstatus & 0x78000000)); /* insert status */ + sim_debug(DEBUG_XIO, &cpu_dev, "STPIO ret rchsa %04x lchsa %04x status %08x\n", + rchsa, lchsa, rstatus); + break; + + case 0x05: /* Reset channel RSCHNL */ + if ((TRAPME = rschnlxio(lchsa, &rstatus))) + goto newpsd; /* error returned, trap cpu */ + /* SPAD entries for interrupts begin at 0x80 */ + INTS[ix] &= ~INTS_REQ; /* clears any requests */ + INTS[ix] &= ~INTS_ACT; /* deactivate specified int level */ + SPAD[ix+0x80] &= ~SINT_ACT; /* deactivate in SPAD too */ + PSD1 = ((PSD1 & 0x87fffffe) | (rstatus & 0x78000000)); /* insert status */ + sim_debug(DEBUG_XIO, &cpu_dev, "RSCHNL rschnlxio ret rchsa %04x lchsa %04x status %08x\n", + rchsa, lchsa, rstatus); + break; + + case 0x06: /* Halt I/O HIO */ + if ((TRAPME = haltxio(lchsa, &rstatus))) + goto newpsd; /* error returned, trap cpu */ + PSD1 = ((PSD1 & 0x87fffffe) | (rstatus & 0x78000000)); /* insert status */ + sim_debug(DEBUG_XIO, &cpu_dev, + "HIO haltxio ret rchsa %04x lchsa %04x status %08x\n", + rchsa, lchsa, rstatus); + break; + + case 0x07: /* Grab controller GRIO n/u */ + if ((TRAPME = grabxio(lchsa, &rstatus))) + goto newpsd; /* error returned, trap cpu */ + PSD1 = ((PSD1 & 0x87fffffe) | (rstatus & 0x78000000)); /* insert status */ + sim_debug(DEBUG_XIO, &cpu_dev, "GRIO ret rchsa %04x lchsa %04x status %08x\n", + rchsa, lchsa, rstatus); + break; + + case 0x08: /* Reset controller RSCTL */ + if ((TRAPME = rsctlxio(lchsa, &rstatus))) + goto newpsd; /* error returned, trap cpu */ + PSD1 = ((PSD1 & 0x87fffffe) | (rstatus & 0x78000000)); /* insert status */ + sim_debug(DEBUG_XIO, &cpu_dev, "RSCTL ret rchsa %04x lchsa %04x status %08x\n", + rchsa, lchsa, rstatus); + break; + + case 0x0C: /* Enable channel interrupt ECI */ + /* disable int only */ + sim_debug(DEBUG_XIO, &cpu_dev, + "ECI chsa %04x lchsa %04x spad %08x INTS[%02x] %08x\n", + rchsa, lchsa, t, ix, INTS[ix]); + + if ((TRAPME = checkxio(lchsa, &rstatus))) + goto newpsd; /* error returned, trap cpu */ + sim_debug(DEBUG_XIO, &cpu_dev, + "ECI after checkxio rchsa %04x suba %04x status %08x\n", + rchsa, suba, rstatus); + + if ((INTS[ix] & INTS_ACT) == 0) + sim_debug(DEBUG_XIO, &cpu_dev, + "ECI INT %02x is NOT set rchsa %04x lchsa %04x status %08x\n", + ix, rchsa, lchsa, rstatus); + /* SPAD entries for interrupts begin at 0x80 */ + INTS[ix] |= INTS_ENAB; /* enable specified int level */ + SPAD[ix+0x80] |= SINT_ENAB; /* enable in SPAD too */ + irq_pend = 1; /* start scanning interrupts again */ + /* return status of zero for present and functioning */ + PSD1 = ((PSD1 & 0x87fffffe) | (rstatus & 0x78000000)); /* insert status */ + break; + + case 0x0D: /* Disable channel interrupt DCI */ + /* disable int, leave req */ + sim_debug(DEBUG_XIO, &cpu_dev, + "DCI rchsa %04x lchsa %04x spad %08x INTS[%02x] %08x\n", + rchsa, lchsa, t, ix, INTS[ix]); + + if ((TRAPME = checkxio(lchsa, &rstatus))) + goto newpsd; /* error returned, trap cpu */ + sim_debug(DEBUG_XIO, &cpu_dev, + "DCI After checkxio call rstatus %08x\n", rstatus); + /* doc says we need to drop 1 queued status entry too */ + if ((INTS[ix] & INTS_ACT) == 0) + sim_debug(DEBUG_XIO, &cpu_dev, + "DCI INT %02x is NOT set rchsa %04x lchsa %04x status %08x\n", + ix, rchsa, lchsa, rstatus); + /* SPAD entries for interrupts begin at 0x80 */ + INTS[ix] &= ~INTS_ENAB; /* disable specified int level */ + SPAD[ix+0x80] &= ~SINT_ENAB; /* disable in SPAD too */ + PSD1 = ((PSD1 & 0x87fffffe) | (rstatus & 0x78000000)); /* insert status */ + break; + + case 0x0E: /* Activate channel interrupt ACI */ + /* Set int active, clear request */ + sim_debug(DEBUG_XIO, &cpu_dev, + "ACI rchsa %04x lchsa %04x spad %08x INTS[%02x] %08x\n", + rchsa, lchsa, t, ix, INTS[ix]); + + if ((TRAPME = checkxio(lchsa, &rstatus))) + goto newpsd; /* error returned, trap cpu */ + if ((INTS[ix] & INTS_ACT) == 0) + sim_debug(DEBUG_XIO, &cpu_dev, + "ACI INT %02x is NOT set rchsa %04x lchsa %04x status %08x\n", + ix, rchsa, lchsa, rstatus); + /* SPAD entries for interrupts begin at 0x80 */ + INTS[ix] |= INTS_ACT; /* activate specified int level */ + SPAD[ix+0x80] |= SINT_ACT; /* enable in SPAD too */ + PSD1 = ((PSD1 & 0x87fffffe) | (rstatus & 0x78000000)); /* insert status */ + break; + + case 0x0F: /* Deactivate channel interrupt DACI */ + /* Clear active and leave any request */ + /* Note, instruction following DACI is not interruptable */ + sim_debug(DEBUG_XIO, &cpu_dev, + "DACI rchsa %04x lchsa %04x spad %08x INTS[%02x] %08x\n", + rchsa, lchsa, t, ix, INTS[ix]); + + if ((TRAPME = checkxio(rchsa, &rstatus))) + goto newpsd; /* error returned, trap cpu */ + if ((INTS[ix] & INTS_ACT) == 0) + sim_debug(DEBUG_XIO, &cpu_dev, + "DACI INT %02x is NOT set chan %04x suba %04x status %08x\n", + ix, chan, suba, rstatus); + /* SPAD entries for interrupts begin at 0x80 */ + INTS[ix] &= ~INTS_ACT; /* deactivate specified int level */ + SPAD[ix+0x80] &= ~SINT_ACT; /* deactivate in SPAD too */ + irq_pend = 1; /* start scanning interrupts again */ + skipinstr = 1; /* skip interrupt test */ + PSD1 = ((PSD1 & 0x87fffffe) | (rstatus & 0x78000000)); /* insert status */ + sim_debug(DEBUG_XIO, &cpu_dev, + "DACI ret lchsa %04x status %08x spad %08x INTS[%02x] %08x BLK %1x\n", + lchsa, rstatus, t, ix, INTS[ix], CPUSTATUS&0x80?1:0); + break; + } /* end of XIO switch */ + break; + } /* End of Instruction Switch */ /* [*][*][*][*][*][*][*][*][*][*][*][*][*][*][*][*][*][*][*][*][*][*] */ @@ -6868,7 +6744,7 @@ mcheck: temp = (uint32)(dest >> 32); /* move upper 32 bits to lo 32 bits */ break; - case 0: /* word store */ + case 0: /* word store */ temp = (uint32)(dest & FMASK); /* mask 32 bit of reg */ if ((addr & 3) != 0) { /* Address fault */ @@ -6877,7 +6753,7 @@ mcheck: } break; - case 1: /* left halfword write */ + case 1: /* left halfword write */ temp &= RMASK; /* mask out 16 left most bits */ temp |= (uint32)(dest & RMASK) << 16; /* put into left most 16 bits */ if ((addr & 1) != 1) { @@ -6887,7 +6763,7 @@ mcheck: } break; - case 3: /* right halfword write */ + case 3: /* right halfword write */ temp &= LMASK; /* mask out 16 right most bits */ temp |= (uint32)(dest & RMASK); /* put into right most 16 bits */ if ((addr & 3) != 3) { @@ -6899,7 +6775,7 @@ mcheck: case 4: case 5: case 6: - case 7: /* byte store operation */ + case 7: /* byte store operation */ temp &= ~(0xFF << (8 * (7 - FC))); /* clear the byte to store */ temp |= (uint32)(dest & 0xFF) << (8 * (7 - FC)); /* insert new byte */ break; @@ -6993,7 +6869,7 @@ mcheck: sim_debug(DEBUG_INST, &cpu_dev, " B4=%.8x B5=%.8x B6=%.8x B7=%.8x\n", BR[4], BR[5], BR[6], BR[7]); } - continue; /* keep running */ + continue; /* keep running */ newpsd: /* Trap Context Block - 6 words */ @@ -7001,24 +6877,24 @@ newpsd: /* WD2 Old PSD Wd 2 */ /* WD3 New PSD WD 1 */ /* WD4 New PSD Wd 2 */ - /* WD5 Multi Use */ /* N/U for Interrupts */ - /* WD6 Multi Use */ /* N/U for Interrupts */ + /* WD5 Multi Use */ /* N/U for Interrupts */ + /* WD6 Multi Use */ /* N/U for Interrupts */ - /* WD5 Multi Use */ /* IOCL address for I/O */ - /* WD6 Multi Use */ /* Status address for I/O */ + /* WD5 Multi Use */ /* IOCL address for I/O */ + /* WD6 Multi Use */ /* Status address for I/O */ - /* WD5 Multi Use */ /* Secondary vector table for SVC */ - /* WD6 Multi Use */ /* N/U for SVC */ + /* WD5 Multi Use */ /* Secondary vector table for SVC */ + /* WD6 Multi Use */ /* N/U for SVC */ - /* WD5 Multi Use */ /* Trap status word for traps */ - /* WD6 Multi Use */ /* N/U for traps */ + /* WD5 Multi Use */ /* Trap status word for traps */ + /* WD6 Multi Use */ /* N/U for traps */ - /* WD5 Multi Use */ /* Trap status word for page faults */ - /* WD6 Multi Use */ /* Page fault status word */ - /* Bit 0 = 0 The map fault was caused by an instruction fetch */ - /* = 1 The mp fault was caused by an operand access */ - /* Bits 1-20 Always zero */ - /* Map register number (logical map block number) */ + /* WD5 Multi Use */ /* Trap status word for page faults */ + /* WD6 Multi Use */ /* Page fault status word */ + /* Bit 0 = 0 The map fault was caused by an instruction fetch */ + /* = 1 The mp fault was caused by an operand access */ + /* Bits 1-20 Always zero */ + /* Map register number (logical map block number) */ /* we get here from a LPSD, LPSDCM, INTR, or TRAP */ if (TRAPME) { @@ -7116,7 +6992,7 @@ newpsd: /* next line changed to force halt on halt trap */ /* TRIED 041320 for MPX3.X install and testing */ if (((tvl == 0) || (CPUSTATUS & 0x40) == 0) || - (TRAPME == PRIVHALT_TRAP)) { /* 0xB8 PL0E Privlege Mode Halt Trap */ + (TRAPME == PRIVHALT_TRAP)) { /* 0xB8 PL0E Privlege Mode Halt Trap */ #endif /* vector is zero or software has not enabled traps yet */ /* execute a trap halt */ @@ -7204,7 +7080,7 @@ newpsd: /* Set map number */ /* pfault will have 11 bit page number and bit 0 set if op fetch */ sim_debug(DEBUG_TRAP, &cpu_dev, - "PAGE TRAP %04x TSTAT %08x LOAD MAPS PSD1 %08x PSD2 %08x CPUSTAT %08x pfault %08x\n", + "PAGE TRAP %04x TSTAT %08x LOAD MAPS PSD1 %08x PSD2 %08x CPUSTAT %08x pfault %08x\n", TRAPME, TRAPSTATUS, PSD1, PSD2, CPUSTATUS, pfault); } TRAPSTATUS = CPUSTATUS & 0x57; /* clear all trap status except cpu type */ @@ -7233,15 +7109,15 @@ newpsd: /* DEBUG_INST support code */ /* output mapped/unmapped */ if (MODES & BASEBIT) { - if (MODES & MAPMODE) - sim_debug(DEBUG_INST, &cpu_dev, "BM%.8x %.8x %.8x ", OPSD1, PSD2, OIR); - else - sim_debug(DEBUG_INST, &cpu_dev, "BU%.8x %.8x %.8x ", OPSD1, PSD2, OIR); + if (MODES & MAPMODE) + sim_debug(DEBUG_INST, &cpu_dev, "BM%.8x %.8x %.8x ", OPSD1, PSD2, OIR); + else + sim_debug(DEBUG_INST, &cpu_dev, "BU%.8x %.8x %.8x ", OPSD1, PSD2, OIR); } else { - if (MODES & MAPMODE) - sim_debug(DEBUG_INST, &cpu_dev, "NM%.8x %.8x %.8x ", OPSD1, PSD2, OIR); - else - sim_debug(DEBUG_INST, &cpu_dev, "NU%.8x %.8x %.8x ", OPSD1, PSD2, OIR); + if (MODES & MAPMODE) + sim_debug(DEBUG_INST, &cpu_dev, "NM%.8x %.8x %.8x ", OPSD1, PSD2, OIR); + else + sim_debug(DEBUG_INST, &cpu_dev, "NU%.8x %.8x %.8x ", OPSD1, PSD2, OIR); } if (cpu_dev.dctrl & DEBUG_INST) fprint_inst(sim_deb, OIR, 0); /* display instruction */ @@ -7250,9 +7126,9 @@ newpsd: sim_debug(DEBUG_INST, &cpu_dev, " R4=%.8x R5=%.8x R6=%.8x R7=%.8x\n", GPR[4], GPR[5], GPR[6], GPR[7]); if (MODES & BASEBIT) { - sim_debug(DEBUG_INST, &cpu_dev, - "\tB0=%.8x B1=%.8x B2=%.8x B3=%.8x", BR[0], BR[1], BR[2], BR[3]); - sim_debug(DEBUG_INST, &cpu_dev, + sim_debug(DEBUG_INST, &cpu_dev, + "\tB0=%.8x B1=%.8x B2=%.8x B3=%.8x", BR[0], BR[1], BR[2], BR[3]); + sim_debug(DEBUG_INST, &cpu_dev, " B4=%.8x B5=%.8x B6=%.8x B7=%.8x\n", BR[4], BR[5], BR[6], BR[7]); } continue; /* single step cpu just for now */ @@ -7264,9 +7140,9 @@ newpsd: /* these are the default ipl devices defined by the CPU jumpers */ /* they can be overridden by specifying IPL device at ipl time */ -uint32 def_disk = 0x0800; /* disk channel 8, device 0 */ -uint32 def_tape = 0x1000; /* tape device 10, device 0 */ -uint32 def_floppy = 0x7ef0; /* IOP floppy disk channel 7e, device f0 */ +uint32 def_disk = 0x0800; /* disk channel 8, device 0 */ +uint32 def_tape = 0x1000; /* tape device 10, device 0 */ +uint32 def_floppy = 0x7ef0; /* IOP floppy disk channel 7e, device f0 */ /* Reset routine */ /* do any one time initialization here for cpu */ @@ -7276,42 +7152,38 @@ t_stat cpu_reset(DEVICE *dptr) t_stat devs = SCPE_OK; /* leave regs alone so values can be passed to boot code */ - PSD1 = 0x80000000; /* privileged, non mapped, non extended, address 0 */ - PSD2 = 0x00004000; /* blocked interrupts mode */ - MODES = (PRIVBIT | BLKMODE); /* set modes to privileged and blocked interrupts */ - CC = 0; /* no CCs too */ - CPUSTATUS = CPU_MODEL; /* clear all cpu status except cpu type */ - CPUSTATUS |= PRIVBIT; /* set privleged state bit 0 */ - CPUSTATUS |= BIT24; /* set blocked mode state bit 24 */ - CPUSTATUS |= BIT22; /* set HS floating point unit not present bit 22 */ - TRAPSTATUS = CPU_MODEL; /* clear all trap status except cpu type */ - CMCR = 0; /* No Cache Enabled */ - SMCR = 0; /* No Shared Memory Enabled */ -//@42 CMSMC = 0xfffffe10; /* No V9 Cache/Shadow Memory Configuration */ -//@ CMSMC = 0x00ff3e10; /* No V9 Cache/Shadow Memory Configuration */ -//@ CMSMC = 0x00ff3e00; /* No V9 Cache/Shadow Memory Configuration */ -//@ CMSMC = 0x00000e10; /* No V9 Cache/Shadow Memory Configuration */ - CMSMC = 0x00ff0a10; /* No V9 Cache/Shadow Memory Configuration */ - CSMCW = 0; /* No V9 CPU Shadow Memory Configuration */ - ISMCW = 0; /* No V9 IPU Shadow Memory Configuration */ - RDYQIN = RDYQOUT = 0; /* initialize cheannel ready queue */ + PSD1 = 0x80000000; /* privileged, non mapped, non extended, address 0 */ + PSD2 = 0x00004000; /* blocked interrupts mode */ + MODES = (PRIVBIT | BLKMODE); /* set modes to privileged and blocked interrupts */ + CC = 0; /* no CCs too */ + CPUSTATUS = CPU_MODEL; /* clear all cpu status except cpu type */ + CPUSTATUS |= PRIVBIT; /* set privleged state bit 0 */ + CPUSTATUS |= BIT24; /* set blocked mode state bit 24 */ + CPUSTATUS |= BIT22; /* set HS floating point unit not present bit 22 */ + TRAPSTATUS = CPU_MODEL; /* clear all trap status except cpu type */ + CMCR = 0; /* No Cache Enabled */ + SMCR = 0; /* No Shared Memory Enabled */ + CMSMC = 0x00ff0a10; /* No V9 Cache/Shadow Memory Configuration */ + CSMCW = 0; /* No V9 CPU Shadow Memory Configuration */ + ISMCW = 0; /* No V9 IPU Shadow Memory Configuration */ + RDYQIN = RDYQOUT = 0; /* initialize cheannel ready queue */ - devs = chan_set_devs(); /* set up the defined devices on the simulator */ + devs = chan_set_devs(); /* set up the defined devices on the simulator */ /* set default breaks to execution tracing */ sim_brk_types = sim_brk_dflt = SWMASK('E'); /* zero regs */ for (i = 0; i < 8; i++) { - GPR[i] = BOOTR[i]; /* set boot register values */ - BR[i] = 0; /* clear the registers */ + GPR[i] = BOOTR[i]; /* set boot register values */ + BR[i] = 0; /* clear the registers */ } /* set console switch settings */ - M[0x780>>2] = CSW; /* set console switch settings */ + M[0x780>>2] = CSW; /* set console switch settings */ /* zero interrupt status words */ for (i = 0; i < 112; i++) - INTS[i] = 0; /* clear interrupt status flags */ + INTS[i] = 0; /* clear interrupt status flags */ /* add code here to initialize the SEL32 cpu scratchpad on initial start */ /* see if spad setup by software, if yes, leave spad alone */ @@ -7320,40 +7192,39 @@ t_stat cpu_reset(DEVICE *dptr) /* Keys are loaded by the O/S software during the boot loading sequence */ if (SPAD[0xf7] != 0xecdab897) { - int ival = 0; /* init value for concept 32 */ + int ival = 0; /* init value for concept 32 */ if (CPU_MODEL < MODEL_27) - ival = 0xfffffff; /* init value for 32/7x int and dev entries */ + ival = 0xfffffff; /* init value for 32/7x int and dev entries */ for (i = 0; i < 1024; i++) - MAPC[i] = 0; /* clear 2048 halfword map cache */ + MAPC[i] = 0; /* clear 2048 halfword map cache */ for (i = 0; i < 224; i++) - SPAD[i] = ival; /* init 128 devices and 96 ints in the spad */ - for (i = 224; i < 256; i++) /* clear the last 32 extries */ - SPAD[i] = 0; /* clear the spad */ - SPAD[0xf0] = 0x80; /* default Trap Table Address (TTA) */ - SPAD[0xf1] = 0x100; /* Interrupt Table Address (ITA) */ - SPAD[0xf2] = 0x700; /* IOCD Base Address */ - SPAD[0xf3] = 0x788; /* Master Process List (MPL) table address */ - SPAD[0xf4] = def_tape; /* Default IPL address from console IPL command or jumper */ - SPAD[0xf5] = 0x00004000; /* current PSD2 defaults to blocked */ - SPAD[0xf6] = 0; /* reserved (PSD1 ??) */ -//UTX SPAD[0xf7] = 0; /* make sure key is zero */ - SPAD[0xf7] = 0xecdab897; /* load the CPU key */ - SPAD[0xf8] = 0x0000f000; /* set DRT to class f (anything else is E) */ - SPAD[0xf9] = CPUSTATUS; /* set default cpu type in cpu status word */ - SPAD[0xff] = 0x00ffffff; /* interrupt level 7f 1's complament */ + SPAD[i] = ival; /* init 128 devices and 96 ints in the spad */ + for (i = 224; i < 256; i++) /* clear the last 32 extries */ + SPAD[i] = 0; /* clear the spad */ + SPAD[0xf0] = 0x80; /* default Trap Table Address (TTA) */ + SPAD[0xf1] = 0x100; /* Interrupt Table Address (ITA) */ + SPAD[0xf2] = 0x700; /* IOCD Base Address */ + SPAD[0xf3] = 0x788; /* Master Process List (MPL) table address */ + SPAD[0xf4] = def_tape; /* Default IPL address from console IPL command or jumper */ + SPAD[0xf5] = 0x00004000; /* current PSD2 defaults to blocked */ + SPAD[0xf6] = 0; /* reserved (PSD1 ??) */ + SPAD[0xf7] = 0xecdab897; /* load the CPU key */ + SPAD[0xf8] = 0x0000f000; /* set DRT to class f (anything else is E) */ + SPAD[0xf9] = CPUSTATUS; /* set default cpu type in cpu status word */ + SPAD[0xff] = 0x00ffffff; /* interrupt level 7f 1's complament */ } /* set low memory bootstrap code */ #if 0 /* moved to boot code in sel32_chan.c so we can reset system and not destroy memory */ - M[0] = 0x02000000; /* 0x00 IOCD 1 read into address 0 */ - M[1] = 0x60000078; /* 0x04 IOCD 1 CMD Chain, Suppress incor length, 120 bytes */ - M[2] = 0x53000000; /* 0x08 IOCD 2 BKSR or RZR to re-read boot code */ - M[3] = 0x60000001; /* 0x0C IOCD 2 CMD chain,Supress incor length, 1 byte */ - M[4] = 0x02000000; /* 0x10 IOCD 3 Read into address 0 */ - M[5] = 0x000006EC; /* 0x14 IOCD 3 Read 0x6EC bytes */ + M[0] = 0x02000000; /* 0x00 IOCD 1 read into address 0 */ + M[1] = 0x60000078; /* 0x04 IOCD 1 CMD Chain, Suppress incor len, 120 bytes */ + M[2] = 0x53000000; /* 0x08 IOCD 2 BKSR or RZR to re-read boot code */ + M[3] = 0x60000001; /* 0x0C IOCD 2 CMD chain,Supress incor length, 1 byte */ + M[4] = 0x02000000; /* 0x10 IOCD 3 Read into address 0 */ + M[5] = 0x000006EC; /* 0x14 IOCD 3 Read 0x6EC bytes */ #endif - loading = 0; /* not loading yet */ + loading = 0; /* not loading yet */ /* we are good to go or error from device setup */ if (devs != SCPE_OK) return devs; @@ -7365,7 +7236,7 @@ t_stat cpu_reset(DEVICE *dptr) t_stat cpu_ex(t_value *vptr, t_addr baddr, UNIT *uptr, int32 sw) { uint32 status, realaddr, prot; - uint32 addr = (baddr & 0xfffffc) >> 2; /* make 24 bit byte address into word address */ + uint32 addr = (baddr & 0xfffffc) >> 2; /* make 24 bit byte address into word address */ if (sw & SWMASK('V')) { /* convert address to real physical address */ @@ -7375,15 +7246,15 @@ t_stat cpu_ex(t_value *vptr, t_addr baddr, UNIT *uptr, int32 sw) *vptr = (M[realaddr] >> (8 * (3 - (baddr & 0x3)))); /* return memory contents */ return SCPE_OK; /* we are all ok */ } - return SCPE_NXM; /* no, none existant memory error */ + return SCPE_NXM; /* no, none existant memory error */ } /* MSIZE is in 32 bit words */ - if (!MEM_ADDR_OK(addr)) /* see if address is within our memory */ - return SCPE_NXM; /* no, none existant memory error */ - if (vptr == NULL) /* any address specified by user */ - return SCPE_OK; /* no, just ignore the request */ - *vptr = (M[addr] >> (8 * (3 - (baddr & 0x3)))); /* return memory contents */ - return SCPE_OK; /* we are all ok */ + if (!MEM_ADDR_OK(addr)) /* see if address is within our memory */ + return SCPE_NXM; /* no, none existant memory error */ + if (vptr == NULL) /* any address specified by user */ + return SCPE_OK; /* no, just ignore the request */ + *vptr = (M[addr] >> (8 * (3 - (baddr & 0x3)))); /* return memory contents */ + return SCPE_OK; /* we are all ok */ } /* Memory deposit */ @@ -7391,15 +7262,15 @@ t_stat cpu_ex(t_value *vptr, t_addr baddr, UNIT *uptr, int32 sw) /* address is byte address with bits 30,31 = 0 */ t_stat cpu_dep(t_value val, t_addr baddr, UNIT *uptr, int32 sw) { - uint32 addr = (baddr & 0xfffffc) >> 2; /* make 24 bit byte address into word address */ + uint32 addr = (baddr & 0xfffffc) >> 2; /* make 24 bit byte address into word address */ static const uint32 bmasks[4] = {0x00FFFFFF, 0xFF00FFFF, 0xFFFF00FF, 0xFFFFFF00}; /* MSIZE is in 32 bit words */ - if (!MEM_ADDR_OK(addr)) /* see if address is within our memory */ - return SCPE_NXM; /* no, none existant memory error */ + if (!MEM_ADDR_OK(addr)) /* see if address is within our memory */ + return SCPE_NXM; /* no, none existant memory error */ val = (M[addr] & bmasks[baddr & 0x3]) | (val << (8 * (3 - (baddr & 0x3)))); - M[addr] = val; /* set new value */ - return SCPE_OK; /* all OK */ + M[addr] = val; /* set new value */ + return SCPE_OK; /* all OK */ } /* set the CPU memory size */ @@ -7425,26 +7296,26 @@ t_stat cpu_set_size(UNIT *uptr, int32 sval, CONST char *cptr, void *desc) int32 val = (int32)sval; t_addr msize; - val >>= UNIT_V_MSIZE; /* shift index right 19 bits */ + val >>= UNIT_V_MSIZE; /* shift index right 19 bits */ if (val >= (int32)(sizeof(memwds)/sizeof(uint32))) /* is size valid */ - return SCPE_ARG; /* nope, argument error */ - sz = memwds[val]; /* (128KB/4) << index == memory size in KW */ - if ((sz <= 0) || (sz > MAXMEMSIZE)) /* is size valid */ - return SCPE_ARG; /* nope, argument error */ - msize = sz << 2; /* Convert to words */ - if (msize < MEMSIZE) { /* is size smaller */ - uint32 mc = 0; /* yes, see if larger memory was used */ + return SCPE_ARG; /* nope, argument error */ + sz = memwds[val]; /* (128KB/4) << index == memory size in KW */ + if ((sz <= 0) || (sz > MAXMEMSIZE)) /* is size valid */ + return SCPE_ARG; /* nope, argument error */ + msize = sz << 2; /* Convert to words */ + if (msize < MEMSIZE) { /* is size smaller */ + uint32 mc = 0; /* yes, see if larger memory was used */ for (i = sz-1; i < (MEMSIZE>>2); i++) - mc = mc | M[i]; /* or in any bits we might find */ + mc = mc | M[i]; /* or in any bits we might find */ if ((mc != 0) && (!get_yn ("Really truncate memory [N]?", FALSE))) - return SCPE_OK; /* forget update */ + return SCPE_OK; /* forget update */ } for (i = (MEMSIZE>>2) - 1; i < sz; i++) - M[i] = 0; /* zero all of the new memory */ - cpu_unit.flags &= ~UNIT_MSIZE; /* clear old size value 0-31 */ - cpu_unit.flags |= val << UNIT_V_MSIZE; /* set new memory size index value (0-31) */ - cpu_unit.capac = (t_addr)msize; /* set new size */ - return SCPE_OK; /* we done */ + M[i] = 0; /* zero all of the new memory */ + cpu_unit.flags &= ~UNIT_MSIZE; /* clear old size value 0-31 */ + cpu_unit.flags |= val << UNIT_V_MSIZE; /* set new memory size index value (0-31) */ + cpu_unit.capac = (t_addr)msize; /* set new size */ + return SCPE_OK; /* we done */ } /* Handle execute history */ @@ -7456,29 +7327,29 @@ cpu_set_hist(UNIT *uptr, int32 val, CONST char *cptr, void *desc) int32 i, lnt; t_stat r; - if (cptr == NULL) { /* check for any user options */ - for (i = 0; i < hst_lnt; i++) /* none, so just zero the history */ - hst[i].opsd1 = 0; /* just psd1 for now */ - hst_p = 0; /* start at the beginning */ - return SCPE_OK; /* all OK */ + if (cptr == NULL) { /* check for any user options */ + for (i = 0; i < hst_lnt; i++) /* none, so just zero the history */ + hst[i].opsd1 = 0; /* just psd1 for now */ + hst_p = 0; /* start at the beginning */ + return SCPE_OK; /* all OK */ } /* the user has specified options, process them */ lnt = (int32)get_uint(cptr, 10, HIST_MAX, &r); if ((r != SCPE_OK) || (lnt && (lnt < HIST_MIN))) - return SCPE_ARG; /* arg error for bad input or too small a value */ - hst_p = 0; /* start at beginning */ - if (hst_lnt) { /* if a new length was input, resize history buffer */ - free(hst); /* out with the old */ - hst_lnt = 0; /* no length anymore */ - hst = NULL; /* and no pointer either */ + return SCPE_ARG; /* arg error for bad input or too small a value */ + hst_p = 0; /* start at beginning */ + if (hst_lnt) { /* if a new length was input, resize history buffer */ + free(hst); /* out with the old */ + hst_lnt = 0; /* no length anymore */ + hst = NULL; /* and no pointer either */ } - if (lnt) { /* see if new size specified, if so get new resized buffer */ + if (lnt) { /* see if new size specified, if so get new resized bfer */ hst = (struct InstHistory *)calloc(sizeof(struct InstHistory), lnt); if (hst == NULL) - return SCPE_MEM; /* allocation error, so tell user */ - hst_lnt = lnt; /* set new length */ + return SCPE_MEM; /* allocation error, so tell user */ + hst_lnt = lnt; /* set new length */ } - return SCPE_OK; /* we are good to go */ + return SCPE_OK; /* we are good to go */ } /* Show history */ @@ -7489,19 +7360,19 @@ t_stat cpu_show_hist(FILE *st, UNIT *uptr, int32 val, CONST void *desc) t_stat r; struct InstHistory *h; - if (hst_lnt == 0) /* see if show history is enabled */ - return SCPE_NOFNC; /* no, so we are out of here */ - if (cptr) { /* see if user provided a display count */ + if (hst_lnt == 0) /* see if show history is enabled */ + return SCPE_NOFNC; /* no, so we are out of here */ + if (cptr) { /* see if user provided a display count */ lnt = (int32)get_uint(cptr, 10, hst_lnt, &r); /* get the count */ - if ((r != SCPE_OK) || (lnt == 0)) /* if error or 0 count */ - return SCPE_ARG; /* report argument error */ + if ((r != SCPE_OK) || (lnt == 0)) /* if error or 0 count */ + return SCPE_ARG; /* report argument error */ } else - lnt = hst_lnt; /* dump all the entries */ - di = hst_p - lnt; /* work forward */ + lnt = hst_lnt; /* dump all the entries */ + di = hst_p - lnt; /* work forward */ if (di < 0) - di = di + hst_lnt; /* wrap */ - for (k = 0; k < lnt; k++) { /* print specified entries */ - h = &hst[(++di) % hst_lnt]; /* entry pointer */ + di = di + hst_lnt; /* wrap */ + for (k = 0; k < lnt; k++) { /* print specified entries */ + h = &hst[(++di) % hst_lnt]; /* entry pointer */ /* display the instruction and results */ if (MODES & BASEBIT) { if (MODES & MAPMODE) @@ -7515,9 +7386,9 @@ t_stat cpu_show_hist(FILE *st, UNIT *uptr, int32 val, CONST void *desc) fprintf(st, "NU%.8x %.8x %.8x ", h->opsd1, h->npsd2, h->oir); } if (h->modes & BASEBIT) - fprint_inst(st, h->oir, SWMASK('M')); /* display basemode instruction */ + fprint_inst(st, h->oir, SWMASK('M')); /* display basemode instruction */ else - fprint_inst(st, h->oir, SWMASK('N')); /* display non basemode instruction */ + fprint_inst(st, h->oir, SWMASK('N')); /* display non basemode instruction */ fprintf(st, "\n"); fprintf(st, "\tR0=%.8x R1=%.8x R2=%.8x R3=%.8x", h->reg[0], h->reg[1], h->reg[2], h->reg[3]); fprintf(st, " R4=%.8x R5=%.8x R6=%.8x R7=%.8x", h->reg[4], h->reg[5], h->reg[6], h->reg[7]); @@ -7527,23 +7398,23 @@ t_stat cpu_show_hist(FILE *st, UNIT *uptr, int32 val, CONST void *desc) fprintf(st, " B4=%.8x B5=%.8x B6=%.8x B7=%.8x", h->reg[12], h->reg[13], h->reg[14], h->reg[15]); } fprintf(st, "\n"); - } /* end for */ - return SCPE_OK; /* all is good */ + } /* end for */ + return SCPE_OK; /* all is good */ } /* return description for the specified device */ const char *cpu_description (DEVICE *dptr) { - return "SEL 32 CPU"; /* return description */ + return "SEL 32 CPU"; /* return description */ } t_stat cpu_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr) { fprintf(st, "The CPU can maintain a history of the most recently executed instructions.\n"); fprintf(st, "This is controlled by the SET CPU HISTORY and SHOW CPU HISTORY commands:\n\n"); - fprintf(st, " sim> SET CPU HISTORY clear history buffer\n"); - fprintf(st, " sim> SET CPU HISTORY=0 disable history\n"); - fprintf(st, " sim> SET CPU HISTORY=n{:file} enable history, length = n\n"); - fprintf(st, " sim> SHOW CPU HISTORY print CPU history\n"); + fprintf(st, " sim> SET CPU HISTORY clear history buffer\n"); + fprintf(st, " sim> SET CPU HISTORY=0 disable history\n"); + fprintf(st, " sim> SET CPU HISTORY=n{:file} enable history, length = n\n"); + fprintf(st, " sim> SHOW CPU HISTORY print CPU history\n"); return SCPE_OK; } diff --git a/SEL32/sel32_defs.h b/SEL32/sel32_defs.h index 8d674b2..0af2d26 100644 --- a/SEL32/sel32_defs.h +++ b/SEL32/sel32_defs.h @@ -479,7 +479,6 @@ extern DEBTAB dev_debug[]; /* write halfword to memory address */ #define WMH(a,d) ((a)&2?(M[(a)>>2]=(M[(a)>>2]&LMASK)|((d)&RMASK)):(M[(a)>>2]=(M[(a)>>2]&RMASK)|((d)<<16))) /* write byte to memory */ -//#define WMB(a,d) (M[(a)>>2]=(((M[(a)>>2])&(~(0xff<<(8*(7-(a&3))))))|((d&0xff)<<(8*(7-(a&3)))))) #define WMB(a,d) (M[(a)>>2]=(((M[(a)>>2])&(~(0xff<<(8*(3-(a&3))))))|((d&0xff)<<(8*(3-(a&3)))))) /* map register access macros */ diff --git a/SEL32/sel32_ec.c b/SEL32/sel32_ec.c index 168c1bf..7003f93 100644 --- a/SEL32/sel32_ec.c +++ b/SEL32/sel32_ec.c @@ -1,6 +1,7 @@ /* sel32_ec.c: SEL-32 8516 Ethernet controller. - Copyright (c) 2020, Richard Cornwell + Copyright (c) 2020-2021, Richard Cornwell + Portions provided by James C. Bevier and other SIMH contributers Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -221,6 +222,11 @@ static CONST ETH_MAC broadcast_ethaddr = {0xff,0xff,0xff,0xff,0xff,0xff}; //CHANP ec_chp[8] = {0}; CHANP ec_chp[NUM_UNITS_ETHER] = {0}; +/* forward definitions */ +#define FOR_TEST +#ifdef FOR_TEST +uint16 ec_preio(UNIT *uptr, uint16 chan); +#endif uint16 ec_startcmd(UNIT *uptr, uint16 chan, uint8 cmd); t_stat ec_rec_srv(UNIT *uptr); t_stat ec_srv(UNIT *uptr); @@ -229,7 +235,9 @@ uint16 ec_iocl(CHANP *chp, int32 tic_ok); void ec_packet_debug(struct ec_device *ec, const char *action, ETH_PACK *packet); t_stat ec_reset (DEVICE *dptr); void ec_ini(UNIT *, t_bool); +#ifdef FOR_TEST uint16 ec_rschnlio(UNIT *uptr); +#endif t_stat ec_show_mac (FILE* st, UNIT* uptr, int32 val, CONST void* desc); t_stat ec_set_mac (UNIT* uptr, int32 val, CONST char* cptr, void* desc); t_stat ec_show_mode (FILE* st, UNIT* uptr, int32 val, CONST void* desc); @@ -266,13 +274,21 @@ UNIT ec_unit[] = { }; DIB ec_dib = { +#ifdef FOR_TEST + ec_preio, /* uint16 (*pre_io)(UNIT *uptr, uint16 chan)*/ /* Pre Start I/O */ +#else NULL, /* Pre start I/O */ +#endif ec_startcmd, /* Start a command */ ec_haltio, /* uint16 (*halt_io)(UNIT *uptr) */ /* Halt I/O */ NULL, /* uint16 (*stop_io)(UNIT *uptr) */ /* Stop I/O */ NULL, /* uint16 (*test_io)(UNIT *uptr) */ /* Test I/O */ NULL, /* uint16 (*rsctl_io)(UNIT *uptr) */ /* Reset Controller */ +#ifdef FOR_TEST ec_rschnlio, /* uint16 (*rschnl_io)(UNIT *uptr) */ /* Reset Channel */ +#else + NULL, /* uint16 (*rschnl_io)(UNIT *uptr) */ /* Reset Channel */ +#endif ec_iocl, /* uint16 (*iocl_io)(CHANP *chp, int32 tic_ok)) */ /* Process IOCL */ ec_ini, /* void (*dev_ini)(UNIT *uptr) */ /* init function */ ec_unit, /* UNIT *units */ /* Pointer to units structure */ @@ -595,18 +611,40 @@ loop: return 0; /* good return */ } +#ifdef FOR_TEST +/* start an ethernet operation */ +uint16 ec_preio(UNIT *uptr, uint16 chan) { + DEVICE *dptr = get_dev(uptr); + int unit = (uptr - dptr->units); + uint16 chsa = GET_UADDR(uptr->CMD); + +#ifdef WAIT_FOR_TEST + sim_debug(DEBUG_CMD, dptr, "ec_preio CMD %08x unit %02x chsa %04x\n", + uptr->CMD, unit, chsa); + if ((uptr->CMD & EC_CMDMSK) != 0) { /* just return if busy */ + sim_debug(DEBUG_CMD, dptr, + "ec_preio unit %02x chsa %04x BUSY\n", unit, chsa); + return SNS_BSY; + } +#endif + + sim_debug(DEBUG_CMD, dptr, "ec_preio CMD %08x unit %02x chsa %04x OK\n", + uptr->CMD, unit, chsa); + return SCPE_OK; /* good to go */ +} +#endif /* Start ethernet command */ uint16 ec_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) { DEVICE *dptr = get_dev(uptr); uint16 chsa = GET_UADDR(uptr->CMD); - CHANP *chp = find_chanp_ptr(chsa); /* find the chanp pointer */ + CHANP *chp = find_chanp_ptr(chsa); /* find the chanp pointer */ sim_debug(DEBUG_CMD, dptr, "ec_startcmd chsa %04x unit %d cmd %02x CMD %08x\n", chsa, (int)(uptr - ec_unit), cmd, uptr->CMD); - if ((uptr->CMD & 0xff) != 0) { /* if any status info, we are busy */ + if ((uptr->CMD & 0xff) != 0) { /* if any status info, we are busy */ sim_debug(DEBUG_CMD, dptr, "ec_startcmd busy\n"); return SNS_BSY; } @@ -684,7 +722,7 @@ t_stat ec_srv(UNIT *uptr) { uint16 chsa = GET_UADDR(uptr->CMD); DEVICE *dptr = get_dev(uptr); - CHANP *chp = find_chanp_ptr(chsa); /* get channel prog pointer */ + CHANP *chp = find_chanp_ptr(chsa); /* get channel prog pointer */ int cmd = uptr->CMD & EC_CMDMSK; uint32 mema; int i; @@ -791,9 +829,9 @@ t_stat ec_srv(UNIT *uptr) chan_end(chsa, SNS_CHNEND|SNS_DEVEND); break; - case EC_WRITE: /* Write command 0x01 */ + case EC_WRITE: /* Write command 0x01 */ pirq = 0; - uptr->CMD &= LMASK; /* remove old status bits & cmd */ + uptr->CMD &= LMASK; /* remove old status bits & cmd */ hdr = (struct ec_eth_hdr *)(&ec_data.snd_buff.msg[0]); pck = (uint8 *)(&ec_data.snd_buff.msg[0]); switch (GET_MODE(ec_master_uptr->flags)) { @@ -1001,23 +1039,25 @@ wr_end: break; } for(i = sizeof(struct ec_eth_hdr); i < len; i++) { - if (chan_write_byte(chsa, &pck[i])) { -// if (len < ec_data.conf[9]) { -// sim_debug(DEBUG_DETAIL, &ec_dev, "ec_srv short read size %x %x %x\n",chp->ccw_count, i, ec_data.conf[9]); -// /* diags wants prog check instead of unit check */ -// pirq = 1; - // } + if (chan_write_byte(chsa, &pck[i])) { +// if (len < ec_data.conf[9]) { +// sim_debug(DEBUG_DETAIL, &ec_dev, +// "ec_srv short read size %x %x %x\n", +// chp->ccw_count, i, ec_data.conf[9]); +// /* diags wants prog check instead of unit check */ +// pirq = 1; +// } ec_data.xtr_ptr = (ec_data.xtr_ptr + 1) & 0xf; ec_data.rx_count++; sim_debug(DEBUG_DETAIL, &ec_dev, - "ec_srv received bytes %d of %d count=%08x\n" ,i, - len, ec_data.rx_count); + "ec_srv received bytes %d of %d count=%08x\n" ,i, + len, ec_data.rx_count); chan_end(chsa, SNS_CHNEND|SNS_DEVEND|STATUS_LENGTH); return SCPE_OK; } } chp->ccw_flags |= FLAG_SLI; -// chp->ccw_cmd = 0; /* This is to kill SLI indicator */ +// chp->ccw_cmd = 0; /* This is to kill SLI indicator */ ec_data.xtr_ptr = (ec_data.xtr_ptr + 1) & 0xf; sim_debug(DEBUG_DETAIL, &ec_dev, "ec_srv received bytes %d count=%08x\n" ,len, ec_data.rx_count); @@ -1043,10 +1083,10 @@ wr_end: chan_end(chsa, SNS_CHNEND|SNS_DEVEND); break; - case EC_STATS: /* Read Statistics */ + case EC_STATS: /* Read Statistics */ ch = 0; /* First 5 words are always zero since these errors are not supported */ - uptr->CMD &= LMASK; /* remove old status bits & cmd */ + uptr->CMD &= LMASK; /* remove old status bits & cmd */ for (i = 0; i < STAT_LEN * 2; i++) { if (i == 6) ch = (ec_data.drop_cnt >> 8) & 0xff; @@ -1079,8 +1119,8 @@ wr_end: chan_end(chsa, SNS_CHNEND|SNS_DEVEND); break; - case EC_CSTATS: /* Clear software counters */ - uptr->CMD &= LMASK; /* remove old status bits & cmd */ + case EC_CSTATS: /* Clear software counters */ + uptr->CMD &= LMASK; /* remove old status bits & cmd */ ec_data.rx_count = ec_data.tx_count = 0; (void)chan_read_byte(chsa, &ch); sim_debug(DEBUG_CMD, dptr, @@ -1089,24 +1129,24 @@ wr_end: chan_end(chsa, SNS_CHNEND|SNS_DEVEND); break; - case EC_NOP: /* NOP 0x03 */ - uptr->CMD &= LMASK; /* remove old status bits & cmd */ + case EC_NOP: /* NOP 0x03 */ + uptr->CMD &= LMASK; /* remove old status bits & cmd */ sim_debug(DEBUG_CMD, dptr, "ec_srv cmd NOP chsa %04x count %04x completed\n", chsa, chp->ccw_count); /* diags want the count to be returned zero */ - chp->ccw_count = 0; /* NOP command count */ + chp->ccw_count = 0; /* NOP command count */ chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* return OK */ break; - case EC_SNS: /* 0x4 */ + case EC_SNS: /* 0x4 */ sim_debug(DEBUG_CMD, dptr, "ec_startcmd CMD sense cnt %02x\n", chp->ccw_count); - uptr->CMD &= LMASK; /* remove old status bits & cmd */ + uptr->CMD &= LMASK; /* remove old status bits & cmd */ /* diags want incorrect length or prog check */ if (chp->ccw_count < 0x04) { - chp->ccw_count = 0; /* zero command count */ + chp->ccw_count = 0; /* zero command count */ if ((chp->ccw_flags & FLAG_SLI) == 0) { /* diag wants incorrect length */ chan_end(chsa, SNS_CHNEND|SNS_DEVEND|STATUS_LENGTH); @@ -1153,7 +1193,7 @@ wr_end: #ifdef ALLOW_0_CMD sim_debug(DEBUG_CMD, dptr, "invalid command %02x\n", cmd); uptr->SNS |= SNS_CMDREJ; - uptr->CMD &= LMASK; /* remove old status bits & cmd */ + uptr->CMD &= LMASK; /* remove old status bits & cmd */ chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); #else sim_debug(DEBUG_CMD, dptr, "for testing, allow unknown command %02x\n", cmd); @@ -1177,26 +1217,26 @@ uint16 ec_haltio(UNIT *uptr) { /* UTX wants SLI bit, but no unit exception */ /* status must not have an error bit set */ /* otherwise, UTX will panic with "bad status" */ - if ((uptr->CMD & EC_CMDMSK) != 0) { /* is unit busy */ + if ((uptr->CMD & EC_CMDMSK) != 0) { /* is unit busy */ sim_debug(DEBUG_CMD, dptr, "ec_haltio HIO chsa %04x cmd = %02x ccw_count %02x\n", chsa, cmd, chp->ccw_count); // stop any I/O and post status and return error status */ - chp->chan_byte = BUFF_EMPTY; /* there is no data to read/store */ - chp->ccw_count = 0; /* zero the count */ - chp->ccw_flags &= ~(FLAG_DC|FLAG_CC);/* stop any chaining */ - uptr->CMD &= LMASK; /* make non-busy */ - uptr->SNS = SNS_RCV_RDY; /* status is online & ready */ - sim_cancel(uptr); /* clear the input timer */ + chp->chan_byte = BUFF_EMPTY; /* there is no data to read/store */ + chp->ccw_count = 0; /* zero the count */ + chp->ccw_flags &= ~(FLAG_DC|FLAG_CC); /* stop any chaining */ + uptr->CMD &= LMASK; /* make non-busy */ + uptr->SNS = SNS_RCV_RDY; /* status is online & ready */ + sim_cancel(uptr); /* clear the input timer */ sim_debug(DEBUG_CMD, dptr, "ec_haltio HIO I/O stop chsa %04x cmd = %02x\n", chsa, cmd); chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* force end */ return SCPE_IOERR; } - uptr->CMD &= LMASK; /* make non-busy */ - uptr->SNS = SNS_RCV_RDY; /* status is online & ready */ + uptr->CMD &= LMASK; /* make non-busy */ + uptr->SNS = SNS_RCV_RDY; /* status is online & ready */ sim_debug(DEBUG_CMD, dptr, "ec_haltio HIO I/O not busy chsa %04x cmd = %02x\n", chsa, cmd); - return SCPE_OK; /* not busy */ + return SCPE_OK; /* not busy */ } /* initialize the ethernet */ @@ -1204,8 +1244,8 @@ void ec_ini(UNIT *uptr, t_bool f) { DEVICE *dptr = get_dev(uptr); - uptr->CMD &= LMASK; /* remove old status bits & cmd */ - uptr->SNS = 0; /* save mode value */ + uptr->CMD &= LMASK; /* remove old status bits & cmd */ + uptr->SNS = 0; /* save mode value */ memset(&ec_data.conf[0], 0, sizeof(ec_data.conf)); ec_data.macs_n = 0; ec_data.tx_count = 0; @@ -1222,6 +1262,7 @@ void ec_ini(UNIT *uptr, t_bool f) "EC init device %s on unit EC%04X\n", dptr->name, GET_UADDR(uptr->CMD)); } +#ifdef FOR_TEST /* handle rschnlio cmds for Ethernet */ uint16 ec_rschnlio(UNIT *uptr) { DEVICE *dptr = get_dev(uptr); @@ -1230,9 +1271,10 @@ uint16 ec_rschnlio(UNIT *uptr) { sim_debug(DEBUG_EXP, dptr, "ec_rschnl chsa %04x cmd = %02x\n", chsa, cmd); - ec_ini(uptr, 0); /* reset the unit */ + ec_ini(uptr, 0); /* reset the unit */ return SCPE_OK; } +#endif static char * ipv4_inet_ntoa(struct in_addr ip) @@ -1285,18 +1327,18 @@ void ec_packet_debug(struct ec_device *ec, const char *action, {NULL, 0} }; static const char *icmp_types[] = { - "Echo Reply", // Type 0 + "Echo Reply", // Type 0 "Type 1 - Unassigned", "Type 2 - Unassigned", - "Destination Unreachable", // Type 3 - "Source Quench (Deprecated)", // Type 4 - "Redirect", // Type 5 + "Destination Unreachable", // Type 3 + "Source Quench (Deprecated)", // Type 4 + "Redirect", // Type 5 "Type 6 - Alternate Host Address (Deprecated)", "Type 7 - Unassigned", - "Echo Request", // Type 8 - "Router Advertisement", // Type 9 - "Router Selection", // Type 10 - "Time Exceeded", // Type 11 + "Echo Request", // Type 8 + "Router Advertisement", // Type 9 + "Router Selection", // Type 10 + "Time Exceeded", // Type 11 "Type 12 - Parameter Problem", "Type 13 - Timestamp", "Type 14 - Timestamp Reply", @@ -1395,13 +1437,15 @@ void ec_packet_debug(struct ec_device *ec, const char *action, sim_debug(DEBUG_TCP, &ec_dev, "%s %s%s %d byte packet from %s:%s to %s:%s\n", action, flags, *flags ? ":" : "", (int)len, src_ip, src_port, dst_ip, dst_port); if (len && (ec_dev.dctrl & DEBUG_TCP)) - sim_data_trace(&ec_dev, ec_unit, payload + 4 * (ntohs(tcp->flags) >> 12), "", len, "", DEBUG_DATA); + sim_data_trace(&ec_dev, ec_unit, payload + + 4 * (ntohs(tcp->flags) >> 12), "", len, "", DEBUG_DATA); break; case ICMP_PROTO: icmp = (struct icmp *)payload; len = ntohs(ip->ip_len) - (ip->ip_v_hl & 0xf) * 4; sim_debug(DEBUG_ICMP, &ec_dev, "%s %s %d byte packet from %s to %s\n", action, - (icmp->type < sizeof(icmp_types)/sizeof(icmp_types[0])) ? icmp_types[icmp->type] : "", (int)len, src_ip, dst_ip); + (icmp->type < sizeof(icmp_types)/sizeof(icmp_types[0])) ? + icmp_types[icmp->type] : "", (int)len, src_ip, dst_ip); if (len && (ec_dev.dctrl & DEBUG_ICMP)) sim_data_trace(&ec_dev, ec_unit, payload + sizeof(struct icmp), "", len, "", DEBUG_DATA); break; @@ -1505,7 +1549,7 @@ t_stat ec_attach(UNIT* uptr, CONST char* cptr) free(tptr); return status; } - eth_mac_fmt(&ec_data.mac, buf); /* format ethernet mac address */ + eth_mac_fmt(&ec_data.mac, buf); /* format ethernet mac address */ if (SCPE_OK != eth_check_address_conflict (&ec_data.etherface, &ec_data.mac)) { eth_close(&ec_data.etherface); @@ -1524,7 +1568,7 @@ t_stat ec_attach(UNIT* uptr, CONST char* cptr) uptr->filename = tptr; uptr->flags |= UNIT_ATT; - eth_setcrc(&ec_data.etherface, 0); /* Enable CRC */ + eth_setcrc(&ec_data.etherface, 0); /* Enable CRC */ /* init read queue (first time only) */ status = ethq_init(&ec_data.ReadQ, 8); diff --git a/SEL32/sel32_hsdp.c b/SEL32/sel32_hsdp.c index 25c4697..cc5eccf 100644 --- a/SEL32/sel32_hsdp.c +++ b/SEL32/sel32_hsdp.c @@ -834,8 +834,6 @@ uint16 hsdp_preio(UNIT *uptr, uint16 chan) int32 cnt; sim_debug(DEBUG_CMD, dptr, "hsdp_preio CMD %08x unit %02x\n", uptr->CMD, unit); -//1215 if (IOCLQ_Num(&dibp->ioclq_ptr[unit]) == IOCLQ_SIZE) { -//1217 1f ((cnt = IOCLQ_Num(&dibp->ioclq_ptr[unit])) >= (IOCLQ_SIZE-2)) { if ((cnt = IOCLQ_Num(&dibp->ioclq_ptr[unit])) >= (IOCLQ_SIZE)) { sim_debug(DEBUG_CMD, dptr, "hsdp_preio CMD %08x unit %02x IOCLQ cnt %02x Full\n", uptr->CMD, unit, cnt); diff --git a/SEL32/sel32_iop.c b/SEL32/sel32_iop.c index e5c0f57..9a24f24 100644 --- a/SEL32/sel32_iop.c +++ b/SEL32/sel32_iop.c @@ -98,7 +98,6 @@ UNIT iop_unit[] = { {UDATA(&iop_srv, UNIT_IOP, 0), 0, UNIT_ADDR(0x7E00)}, /* Channel controller */ }; -//DIB iop_dib = {NULL, iop_startcmd, NULL, NULL, NULL, iop_ini, iop_unit, iop_chp, NUM_UNITS_IOP, 0xff, 0x7e00,0,0,0}; DIB iop_dib = { NULL, /* uint16 (*pre_io)(UNIT *uptr, uint16 chan)*/ /* Start I/O */ iop_startcmd, /* uint16 (*start_cmd)(UNIT *uptr, uint16 chan, uint8 cmd)*/ /* Start command SIO */ diff --git a/SEL32/sel32_lpr.c b/SEL32/sel32_lpr.c index 144ed48..277d848 100644 --- a/SEL32/sel32_lpr.c +++ b/SEL32/sel32_lpr.c @@ -135,25 +135,27 @@ LPFCTBL EQU $ struct _lpr_data { - uint8 lbuff[160]; /* Output line buffer */ + uint8 lbuff[160]; /* Output line buffer */ }; struct _lpr_data lpr_data[NUM_DEVS_LPR]; -uint16 lpr_startcmd(UNIT *, uint16, uint8); -void lpr_ini(UNIT *, t_bool); -uint16 lpr_rschnlio(UNIT *uptr); -t_stat lpr_srv(UNIT *); -t_stat lpr_reset(DEVICE *); -t_stat lpr_attach(UNIT *, CONST char *); -t_stat lpr_detach(UNIT *); -t_stat lpr_setlpp(UNIT *, int32, CONST char *, void *); -t_stat lpr_getlpp(FILE *, UNIT *, int32, CONST void *); +/* forward definitions */ +uint16 lpr_preio(UNIT *uptr, uint16 chan); +uint16 lpr_startcmd(UNIT *, uint16, uint8); +void lpr_ini(UNIT *, t_bool); +uint16 lpr_rschnlio(UNIT *uptr); +t_stat lpr_srv(UNIT *); +t_stat lpr_reset(DEVICE *); +t_stat lpr_attach(UNIT *, CONST char *); +t_stat lpr_detach(UNIT *); +t_stat lpr_setlpp(UNIT *, int32, CONST char *, void *); +t_stat lpr_getlpp(FILE *, UNIT *, int32, CONST void *); /* channel program information */ -CHANP lpr_chp[NUM_DEVS_LPR] = {0}; +CHANP lpr_chp[NUM_DEVS_LPR] = {0}; -MTAB lpr_mod[] = { +MTAB lpr_mod[] = { {MTAB_XTD|MTAB_VUN|MTAB_VALR, 0, "LINESPERPAGE", "LINESPERPAGE", &lpr_setlpp, &lpr_getlpp, NULL, "Number of lines per page"}, {MTAB_XTD|MTAB_VUN|MTAB_VALR, 0, "DEV", "DEV", &set_dev_addr, @@ -161,7 +163,7 @@ MTAB lpr_mod[] = { {0} }; -UNIT lpr_unit[] = { +UNIT lpr_unit[] = { {UDATA(&lpr_srv, UNIT_LPR, 66), 300, UNIT_ADDR(0x7EF8)}, /* A */ #if NUM_DEVS_LPR > 1 {UDATA(&lpr_srv, UNIT_LPR, 66), 300, UNIT_ADDR(0x7EF9)}, /* B */ @@ -169,10 +171,8 @@ UNIT lpr_unit[] = { }; /* Device Information Block */ -//DIB lpr_dib = {NULL, lpr_startcmd, NULL, NULL, lpr_ini, lpr_unit, -//lpr_chp, NUM_DEVS_LPR, 0xff, 0x7e00, 0, 0, 0}; -DIB lpr_dib = { - NULL, /* uint16 (*pre_io)(UNIT *uptr, uint16 chan)*/ /* Start I/O */ +DIB lpr_dib = { + lpr_preio, /* uint16 (*pre_io)(UNIT *uptr, uint16 chan)*/ /* Pre Start I/O */ lpr_startcmd, /* uint16 (*start_cmd)(UNIT *uptr, uint16 chan, uint8 cmd)*/ /* Start command */ NULL, /* uint16 (*halt_io)(UNIT *uptr) */ /* Halt I/O */ NULL, /* uint16 (*stop_io)(UNIT *uptr) */ /* Stop I/O */ @@ -192,7 +192,7 @@ DIB lpr_dib = { {0} /* uint32 chan_fifo[FIFO_SIZE] */ /* interrupt status fifo for channel */ }; -DEVICE lpr_dev = { +DEVICE lpr_dev = { "LPR", lpr_unit, NULL, lpr_mod, NUM_DEVS_LPR, 8, 15, 1, 8, 8, NULL, NULL, NULL, NULL, &lpr_attach, &lpr_detach, @@ -221,6 +221,25 @@ uint16 lpr_rschnlio(UNIT *uptr) { return SCPE_OK; } +/* start a line printer operation */ +uint16 lpr_preio(UNIT *uptr, uint16 chan) { + DEVICE *dptr = get_dev(uptr); + int unit = (uptr - dptr->units); + uint16 chsa = GET_UADDR(uptr->CMD); + + sim_debug(DEBUG_CMD, dptr, "lpr_preio CMD %08x unit %02x chsa %04x\n", + uptr->CMD, unit, chsa); + if ((uptr->CMD & LPR_CMDMSK) != 0) { /* just return if busy */ + sim_debug(DEBUG_CMD, dptr, + "lpr_preio unit %02x chsa %04x BUSY\n", unit, chsa); + return SNS_BSY; + } + + sim_debug(DEBUG_CMD, dptr, + "lpr_preio unit %02x chsa %04xOK\n", unit, chsa); + return SCPE_OK; /* good to go */ +} + /* start an I/O operation */ uint16 lpr_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) { diff --git a/SEL32/sel32_mt.c b/SEL32/sel32_mt.c index 77d1a82..91bfbea 100644 --- a/SEL32/sel32_mt.c +++ b/SEL32/sel32_mt.c @@ -148,6 +148,8 @@ #define BUF_EMPTY(u) (u->hwmark == 0xFFFFFFFF) #define CLR_BUF(u) u->hwmark = 0xFFFFFFFF +/* forward definitions */ +uint16 mt_preio(UNIT *uptr, uint16 chan); uint16 mt_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) ; t_stat mt_srv(UNIT *uptr); t_stat mt_boot(int32 unitnum, DEVICE *dptr); @@ -292,7 +294,7 @@ UNIT mta_unit[] = { CHANP mta_chp[NUM_UNITS_MT] = {0}; DIB mta_dib = { - NULL, /* uint16 (*pre_io)(UNIT *uptr, uint16 chan)*/ /* Pre Start I/O */ + mt_preio, /* uint16 (*pre_io)(UNIT *uptr, uint16 chan)*/ /* Pre Start I/O */ mt_startcmd, /* uint16 (*start_cmd)(UNIT *uptr, uint16 chan, uint8 cmd)*/ /* Start command */ NULL, /* uint16 (*halt_io)(UNIT *uptr) */ /* Halt I/O */ NULL, /* uint16 (*stop_io)(UNIT *uptr) */ /* Stop I/O */ @@ -340,7 +342,7 @@ UNIT mtb_unit[] = { /* device information block */ DIB mtb_dib = { - NULL, /* uint16 (*pre_io)(UNIT *uptr, uint16 chan)*/ /* Pre Start I/O */ + mt_preio, /* uint16 (*pre_io)(UNIT *uptr, uint16 chan)*/ /* Pre Start I/O */ mt_startcmd, /* uint16 (*start_cmd)(UNIT *uptr, uint16 chan, uint8 cmd)*/ /* Start command */ NULL, /* uint16 (*halt_io)(UNIT *uptr) */ /* Halt I/O */ NULL, /* uint16 (*stop_io)(UNIT *uptr) */ /* Stop I/O */ @@ -369,6 +371,30 @@ DEVICE mtb_dev = { }; #endif +/* start a tape operation */ +uint16 mt_preio(UNIT *uptr, uint16 chan) { + DEVICE *dptr = get_dev(uptr); + int unit = (uptr - dptr->units); + uint16 chsa = GET_UADDR(uptr->CMD); + + sim_debug(DEBUG_CMD, dptr, "mt_preio CMD %08x unit %02x chsa %04x\n", + uptr->CMD, unit, chsa); + if ((uptr->CMD & MT_CMDMSK) != 0) { /* just return if busy */ + sim_debug(DEBUG_CMD, dptr, + "mt_preio unit %02x chsa %04x BUSY\n", unit, chsa); + return SNS_BSY; + } + if ((uptr->flags & UNIT_ATT) == 0) { /* unit attached status */ + uptr->SNS |= SNS_INTVENT; /* unit intervention required */ + uptr->SNS &= ~(SNS_RDY|SNS_ONLN); /* unit not online or rdy */ + uptr->SNS &= ~SNS_LOAD; /* reset BOT detected */ + return SNS_BSY; + } + + sim_debug(DEBUG_CMD, dptr, "mt_preio unit %02x chsa %04xOK\n", unit, chsa); + return SCPE_OK; /* good to go */ +} + /* start an I/O operation */ uint16 mt_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) { @@ -379,15 +405,16 @@ uint16 mt_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) sim_debug(DEBUG_EXP, dptr, "mt_startcmd entry chan %04x cmd %02x\n", chan, cmd); if (mt_busy[GET_DEV_BUF(dptr->flags)] != 0 || (uptr->CMD & MT_CMDMSK) != 0) { - sim_debug(DEBUG_EXP, dptr, "mt_startcmd busy chan %04x cmd %02x\n", chan, cmd); - uptr->flags |= MT_BUSY; /* Flag we need to send CUE */ + sim_debug(DEBUG_EXP, dptr, "mt_startcmd busy %02x chan %04x flags %08x CMD %02x\n", + mt_busy[GET_DEV_BUF(dptr->flags)], chan, dptr->flags, uptr->CMD); + uptr->flags |= MT_BUSY; /* Flag we need to send CUE */ return SNS_BSY; } sim_debug(DEBUG_EXP, dptr, "mt_startcmd processing unit %01x cmd %02x\n", unit, cmd); switch (cmd & 0xFF) { - case 0x00: /* INCH command */ + case 0x00: /* INCH command */ sim_debug(DEBUG_CMD, dptr, "start INCH command\n"); sim_debug(DEBUG_CMD, dptr, @@ -395,24 +422,24 @@ uint16 mt_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) chsa, chp->ccw_addr, chp->ccw_count); /* UTX_needs_interrupt */ - cmd = MT_CMDMSK; /* insert INCH cmd as 0xff */ + cmd = MT_CMDMSK; /* insert INCH cmd as 0xff */ /* fall through */ - case 0x03: /* Tape motion commands or NOP */ - case 0x13: /* Read and compare command */ - case 0x23: /* Rewind command */ - case 0x33: /* Rewind and unload */ - case 0x43: /* Advance record */ - case 0x53: /* Backspace record */ - case 0x63: /* Advance filemark */ - case 0x73: /* Backspace filemark */ - case 0x83: /* Set Mode command */ - case 0x93: /* Write Tape filemark */ - case 0xA3: /* Erase 3.5 of tape */ + case 0x03: /* Tape motion commands or NOP */ + case 0x13: /* Read and compare command */ + case 0x23: /* Rewind command */ + case 0x33: /* Rewind and unload */ + case 0x43: /* Advance record */ + case 0x53: /* Backspace record */ + case 0x63: /* Advance filemark */ + case 0x73: /* Backspace filemark */ + case 0x83: /* Set Mode command */ + case 0x93: /* Write Tape filemark */ + case 0xA3: /* Erase 3.5 of tape */ /* UTX_needs_interrupt on NOP or INCH */ /* fall through */ - case 0x01: /* Write command */ - case 0x02: /* Read command */ - case 0x0C: /* Read backward */ + case 0x01: /* Write command */ + case 0x02: /* Read command */ + case 0x0C: /* Read backward */ if (cmd == 0x01) sim_debug(DEBUG_EXP, dptr, "mt_startcmd WRITE chan %04x addr %06x cnt %04x\n", @@ -421,30 +448,30 @@ uint16 mt_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) sim_debug(DEBUG_EXP, dptr, "mt_startcmd READ chan %04x addr %06x cnt %04x\n", chan, chp->ccw_addr, chp->ccw_count); - if (cmd != 0x03) /* if this is a nop do not zero status */ + if (cmd != 0x03) /* if this is a nop do not zero status */ uptr->SNS = (uptr->SNS & 0x0000ff00); /* clear all but byte 2 */ - uptr->SNS |= (SNS_RDY|SNS_ONLN); /* set ready status */ + uptr->SNS |= (SNS_RDY|SNS_ONLN); /* set ready status */ /* Fall through */ if (sim_tape_wrp(uptr)) - uptr->SNS |= (SNS_WRP); /* write protected */ + uptr->SNS |= (SNS_WRP); /* write protected */ if (sim_tape_bot(uptr)) - uptr->SNS |= (SNS_LOAD); /* tape at load point */ + uptr->SNS |= (SNS_LOAD); /* tape at load point */ if (sim_tape_eot(uptr)) - uptr->SNS |= (SNS_EOT); /* tape at EOM */ + uptr->SNS |= (SNS_EOT); /* tape at EOM */ /* Fall through */ case 0x04: /* Sense */ - uptr->CMD &= ~(MT_CMDMSK); /* clear out last cmd */ - uptr->CMD |= cmd & MT_CMDMSK; /* insert new cmd */ - CLR_BUF(uptr); /* buffer is empty */ - uptr->POS = 0; /* reset buffer position pointer */ - mt_busy[GET_DEV_BUF(dptr->flags)] = 1; /* show we are busy */ + uptr->CMD &= ~(MT_CMDMSK); /* clear out last cmd */ + uptr->CMD |= cmd & MT_CMDMSK; /* insert new cmd */ + CLR_BUF(uptr); /* buffer is empty */ + uptr->POS = 0; /* reset buffer position pointer */ + mt_busy[GET_DEV_BUF(dptr->flags)] = 1; /* show we are busy */ sim_debug(DEBUG_EXP, dptr, "mt_startcmd sense %08x return 0 chan %04x cmd %02x\n", uptr->SNS, chan, cmd); - sim_activate(uptr, 100); /* Start unit off */ + sim_activate(uptr, 100); /* Start unit off */ return 0; - default: /* invalid command */ + default: /* invalid command */ sim_debug(DEBUG_EXP, dptr, "mt_startcmd CMDREJ return chan %04x cmd %02x\n", chan, cmd); uptr->SNS |= SNS_CMDREJ; @@ -454,7 +481,7 @@ uint16 mt_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) } #if 0 /* not reached */ - if (uptr->SNS & 0xff000000) /* errors? */ + if (uptr->SNS & 0xff000000) /* errors? */ return SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK; sim_debug(DEBUG_EXP, dptr, "mt_startcmd ret CHNEND|DEVEND chan %04x unit %04x cmd %02x\n", chan, unit, cmd); @@ -466,47 +493,49 @@ uint16 mt_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) t_stat mt_error(UNIT *uptr, uint16 chsa, t_stat r, DEVICE *dptr) { sim_debug(DEBUG_CMD, dptr, "mt_error status %08x\n", r); - mt_busy[GET_DEV_BUF(dptr->flags)] &= ~1; /* not busy anymore */ + mt_busy[GET_DEV_BUF(dptr->flags)] &= ~1; /* not busy anymore */ - switch (r) { /* switch on return value */ - case MTSE_OK: /* no error */ - chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* we are done with command */ + switch (r) { /* switch on return value */ + case MTSE_OK: /* no error */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* we are done with command */ break; - case MTSE_TMK: /* tape mark */ + case MTSE_TMK: /* tape mark */ sim_debug(DEBUG_CMD, dptr, "FILE MARK\n"); - uptr->SNS |= SNS_FMRKDT; /* file mark detected */ + uptr->SNS |= SNS_FMRKDT; /* file mark detected */ chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); break; - case MTSE_WRP: /* write protected */ - uptr->SNS |= SNS_WRP; /* write protected */ + case MTSE_WRP: /* write protected */ + uptr->SNS |= SNS_WRP; /* write protected */ sim_debug(DEBUG_CMD, dptr, "WRITE PROTECT %08x\n", r); /* operator intervention */ - chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* we are done with command */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* we are done with command */ break; - case MTSE_UNATT: /* unattached */ - uptr->SNS |= SNS_INTVENT; /* unit intervention required */ + case MTSE_UNATT: /* unattached */ + uptr->SNS |= SNS_INTVENT; /* unit intervention required */ + uptr->SNS &= ~(SNS_RDY|SNS_ONLN); /* unit not online or rdy */ + uptr->SNS &= ~SNS_LOAD; /* reset BOT detected */ sim_debug(DEBUG_CMD, dptr, "ATTENTION %08x\n", r); /* operator intervention */ chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITEXP); break; - case MTSE_IOERR: /* IO error */ - case MTSE_FMT: /* invalid format */ - case MTSE_RECE: /* error in record */ + case MTSE_IOERR: /* IO error */ + case MTSE_FMT: /* invalid format */ + case MTSE_RECE: /* error in record */ sim_debug(DEBUG_CMD, dptr, "ERROR %08x\n", r); - chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* we are done with command */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* we are done with command */ break; - case MTSE_BOT: /* beginning of tape */ - uptr->SNS |= SNS_LOAD; /* tape at BOT */ + case MTSE_BOT: /* beginning of tape */ + uptr->SNS |= SNS_LOAD; /* tape at BOT */ sim_debug(DEBUG_CMD, dptr, "BOT\n"); - chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* we are done with command */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* we are done with command */ break; - case MTSE_INVRL: /* invalid rec lnt */ - case MTSE_EOM: /* end of medium */ - uptr->SNS |= SNS_EOT; /* tape at EOT */ + case MTSE_INVRL: /* invalid rec lnt */ + case MTSE_EOM: /* end of medium */ + uptr->SNS |= SNS_EOT; /* tape at EOT */ sim_debug(DEBUG_CMD, dptr, "EOT\n"); chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITEXP); break; @@ -524,7 +553,7 @@ t_stat mt_srv(UNIT *uptr) int bufnum = GET_DEV_BUF(dptr->flags); CHANP *chp = find_chanp_ptr(chsa); /* find the chanp pointer */ t_mtrlnt reclen; - t_stat r = SCPE_ARG; /* Force error if not set */ + t_stat r = SCPE_ARG; /* Force error if not set */ int i; uint32 mema; uint16 len; @@ -532,10 +561,13 @@ t_stat mt_srv(UNIT *uptr) // uint8 buf[1024]; sim_debug(DEBUG_DETAIL, dptr, "mt_srv unit %04x cmd %02x\n", unit, cmd); - if ((uptr->flags & UNIT_ATT) == 0) { /* unit attached status */ - uptr->SNS |= SNS_INTVENT; /* unit intervention required */ - mt_busy[bufnum] &= ~1; /* make our buffer not busy */ - if (cmd != MT_SENSE) { /* we are completed with unit check status */ + if ((uptr->flags & UNIT_ATT) == 0) { /* unit attached status */ + uptr->SNS |= SNS_INTVENT; /* unit intervention required */ + uptr->SNS &= ~(SNS_RDY|SNS_ONLN); /* unit not online or rdy */ + uptr->SNS &= ~SNS_LOAD; /* reset BOT detected */ + mt_busy[bufnum] &= ~1; /* make our buffer not busy */ + if (cmd != MT_SENSE) { /* we are completed with unit check status */ + uptr->CMD &= ~MT_CMDMSK; /* clear the cmd */ chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); return SCPE_OK; } @@ -543,15 +575,15 @@ t_stat mt_srv(UNIT *uptr) switch (cmd) { case MT_CMDMSK: /* 0x0ff for inch 0x00 */ /* INCH is for channel, nothing for us */ - len = chp->ccw_count; /* INCH command count */ - mema = chp->ccw_addr; /* get inch or buffer addr */ + len = chp->ccw_count; /* INCH command count */ + mema = chp->ccw_addr; /* get inch or buffer addr */ sim_debug(DEBUG_CMD, dptr, "mt_srv starting INCH %06x cmd, chsa %04x MemBuf %06x cnt %04x\n", mema, chsa, chp->ccw_addr, chp->ccw_count); if (len == 0) { /* we have invalid count, error, bail out */ - uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ + uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ uptr->SNS |= SNS_CMDREJ|SNS_EQUCHK; chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); break; @@ -560,7 +592,7 @@ t_stat mt_srv(UNIT *uptr) for (i=0; i < len; i++) { if (chan_read_byte(chsa, &buf[i])) { /* we have error, bail out */ - uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ + uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ uptr->SNS |= SNS_CMDREJ|SNS_EQUCHK; chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); break; @@ -570,11 +602,11 @@ t_stat mt_srv(UNIT *uptr) #endif /* the chp->ccw_addr location contains the inch address */ /* call set_inch() to setup inch buffer */ - i = set_inch(uptr, mema); /* new address */ + i = set_inch(uptr, mema); /* new address */ if ((i == SCPE_MEM) || (i == SCPE_ARG)) { /* any error */ /* we have error, bail out */ - uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ + uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ uptr->SNS |= SNS_CMDREJ|SNS_EQUCHK; chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); break; @@ -582,81 +614,89 @@ t_stat mt_srv(UNIT *uptr) /* set halfwords 16 & 17 to 5 as default retry count in inch data */ /* UTX uses this value to see if the device is a buffered tape processor */ /* they must be non-zero and equal to be BTP */ - WMH(mema+(16<<1),5); /* write left HW with count */ - WMH(mema+(17<<1),5); /* write right HW with count */ + WMH(mema+(16<<1),5); /* write left HW with count */ + WMH(mema+(17<<1),5); /* write right HW with count */ sim_debug(DEBUG_CMD, dptr, "mt_srv cmd INCH chsa %04x chsa %06x count %04x completed INCH16 %08x\n", chsa, mema, chp->ccw_count, RMW(mema+(8<<2))); - uptr->CMD &= ~MT_CMDMSK; /* clear the cmd */ - mt_busy[bufnum] &= ~1; /* make our buffer not busy */ + uptr->CMD &= ~MT_CMDMSK; /* clear the cmd */ + mt_busy[bufnum] &= ~1; /* make our buffer not busy */ chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* we are done dev|chan end */ break; - case 0x80: /* other? */ /* default to NOP */ + case 0x80: /* other? */ /* default to NOP */ sim_debug(DEBUG_CMD, dptr, "mt_srv cmd 80 DIAG unit=%04x SNS %08x\n", unit, uptr->SNS); - ch = (uptr->SNS >> 24) & 0xff; /* get sense byte 0 status */ + ch = (uptr->SNS >> 24) & 0xff; /* get sense byte 0 status */ sim_debug(DEBUG_CMD, dptr, "sense unit %02x byte 0 %02x\n", unit, ch); - chan_write_byte(chsa, &ch); /* write byte 0 */ - ch = (uptr->SNS >> 16) & 0xff; /* get sense byte 1 status */ + chan_write_byte(chsa, &ch); /* write byte 0 */ + ch = (uptr->SNS >> 16) & 0xff; /* get sense byte 1 status */ sim_debug(DEBUG_CMD, dptr, "sense unit %02x byte 1 %02x\n", unit, ch); - chan_write_byte(chsa, &ch); /* write byte 1 */ - ch = (uptr->SNS >> 8) & 0xff; /* get sense byte 2 status */ + chan_write_byte(chsa, &ch); /* write byte 1 */ + ch = (uptr->SNS >> 8) & 0xff; /* get sense byte 2 status */ sim_debug(DEBUG_CMD, dptr, "sense unit %02x byte 2 %02x\n", unit, ch); - chan_write_byte(chsa, &ch); /* write byte 2 */ - ch = (uptr->SNS >> 0) & 0xff; /* get sense byte 3 status */ + chan_write_byte(chsa, &ch); /* write byte 2 */ + ch = (uptr->SNS >> 0) & 0xff; /* get sense byte 3 status */ sim_debug(DEBUG_CMD, dptr, "sense unit %02x byte 3 %02x\n", unit, ch); - chan_write_byte(chsa, &ch); /* write byte 3 */ + chan_write_byte(chsa, &ch); /* write byte 3 */ /* write zero extra status */ for (ch=4; ch < 0xc; ch++) { uint8 zc = 0; - chan_write_byte(chsa, &zc); /* write zero byte */ + chan_write_byte(chsa, &zc); /* write zero byte */ sim_debug(DEBUG_CMD, dptr, "sense unit %02x byte %1x %02x\n", unit, ch, zc); } - uptr->CMD &= ~MT_CMDMSK; /* clear the cmd */ - mt_busy[bufnum] &= ~1; /* make our buffer not busy */ + uptr->CMD &= ~MT_CMDMSK; /* clear the cmd */ + mt_busy[bufnum] &= ~1; /* make our buffer not busy */ + uptr->SNS = (uptr->SNS & 0x0000ff00); /* clear all but byte 2 */ + if ((uptr->flags & UNIT_ATT) == 0) /* unit attached status */ + uptr->SNS |= SNS_INTVENT; /* unit intervention required */ + else + uptr->SNS &= ~(SNS_RDY|SNS_ONLN); /* unit not online or rdy */ sim_debug(DEBUG_CMD, dptr, "mt_srv DIAG SNS %08x char complete unit=%02x\n", uptr->SNS, unit); - chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* we are done dev|chan end */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* we are done dev|chan end */ break; - case MT_NOP: /* 0x03 */ /* NOP motion command */ - uptr->CMD &= ~MT_CMDMSK; /* clear the cmd */ - mt_busy[bufnum] &= ~1; /* make our buffer not busy */ - chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* we are done dev|chan end */ + case MT_NOP: /* 0x03 */ /* NOP motion command */ + uptr->CMD &= ~MT_CMDMSK; /* clear the cmd */ + mt_busy[bufnum] &= ~1; /* make our buffer not busy */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* we are done dev|chan end */ break; - case MT_SENSE: /* 0x04 */ /* get sense data */ + case MT_SENSE: /* 0x04 */ /* get sense data */ /* write requested status */ - len = chp->ccw_count; /* command count */ -//0905 for (i=0; iccw_count; /* command count */ for (i=0; i<4; i++) { ch = 0; if (i<4) ch = (uptr->SNS >> (24-(i*8))) & 0xff; /* get 8 bits of status */ - chan_write_byte(chsa, &ch); /* write zero byte */ + chan_write_byte(chsa, &ch); /* write zero byte */ sim_debug(DEBUG_CMD, dptr, "sense unit %02x byte %1x %02x\n", unit, i, ch); } - uptr->CMD &= ~MT_CMDMSK; /* clear the cmd */ - mt_busy[bufnum] &= ~1; /* make our buffer not busy */ + uptr->CMD &= ~MT_CMDMSK; /* clear the cmd */ + mt_busy[bufnum] &= ~1; /* make our buffer not busy */ + uptr->SNS = (uptr->SNS & 0x0000ff00); /* clear all but byte 2 */ + if ((uptr->flags & UNIT_ATT) == 0) /* unit attached status */ + uptr->SNS |= SNS_INTVENT; /* unit intervention required */ + else + uptr->SNS &= ~(SNS_RDY|SNS_ONLN); /* unit not online or rdy */ sim_debug(DEBUG_CMD, dptr, "mt_srv SENSE %08x char complete unit=%02x\n", uptr->SNS, unit); - chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* we are done dev|chan end */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* we are done dev|chan end */ break; - case MT_READ: /* 0x02 */ /* read a record from the device */ -// sim_debug(DEBUG_DETAIL, dptr, "mt_srv cmd 2 READ unit=%02x\n", unit); - sim_debug(DEBUG_CMD, dptr, "mt_srv cmd 2 READ unit=%02x\n", unit); - if (uptr->CMD & MT_READDONE) { /* is the read complete */ - uptr->SNS &= ~(SNS_LOAD|SNS_EOT); /* reset BOT & EOT */ - if (sim_tape_eot(uptr)) { /* see if at EOM */ - uptr->SNS |= SNS_EOT; /* set EOT status */ + case MT_READ: /* 0x02 */ /* read a record from the device */ + sim_debug(DEBUG_DETAIL, dptr, "mt_srv cmd 2 READ unit=%02x\n", unit); + if (uptr->CMD & MT_READDONE) { /* is the read complete */ + uptr->SNS &= ~(SNS_LOAD|SNS_EOT); /* reset BOT & EOT */ + if (sim_tape_eot(uptr)) { /* see if at EOM */ + uptr->SNS |= SNS_EOT; /* set EOT status */ } uptr->CMD &= ~(MT_CMDMSK|MT_READDONE); /* clear all but readdone & cmd */ - uptr->CMD &= ~MT_CMDMSK; /* clear the cmd */ - mt_busy[bufnum] &= ~1; /* not busy anymore */ + uptr->CMD &= ~MT_CMDMSK; /* clear the cmd */ + mt_busy[bufnum] &= ~1; /* not busy anymore */ sim_debug(DEBUG_CMD, dptr, "mt_srv READ %04x char complete unit=%02x sense %08x\n", uptr->POS, unit, uptr->SNS); @@ -672,10 +712,9 @@ t_stat mt_srv(UNIT *uptr) uptr->CMD &= ~(MT_CMDMSK|MT_READDONE); /* clear all but readdone & cmd */ return mt_error(uptr, chsa, r, dptr); /* process any error & return status */ } - uptr->SNS &= ~(SNS_LOAD|SNS_EOT); /* reset BOT & EOT */ - uptr->POS = 0; /* reset buffer position */ - uptr->hwmark = reclen; /* set buffer chars read in */ -// sim_debug(DEBUG_DETAIL, dptr, "mt_srv READ fill buffer complete count %04x\n", reclen); + uptr->SNS &= ~(SNS_LOAD|SNS_EOT); /* reset BOT & EOT */ + uptr->POS = 0; /* reset buffer position */ + uptr->hwmark = reclen; /* set buffer chars read in */ sim_debug(DEBUG_CMD, dptr, "mt_srv READ fill buffer complete count %04x\n", reclen); sim_debug(DEBUG_CMD, dptr, "mt_srv READ MemBuf %06x cnt %04x %02x%02x%02x%02x\n", @@ -692,20 +731,19 @@ t_stat mt_srv(UNIT *uptr) /* If not read whole record, skip till end */ if ((uint32)uptr->POS < uptr->hwmark) { /* Send dummy character to force SLI */ - chan_write_byte(chsa, &ch); /* write the byte */ + chan_write_byte(chsa, &ch); /* write the byte */ sim_debug(DEBUG_CMD, dptr, "Read unit %02x send dump SLI\n", unit); sim_activate(uptr, (uptr->hwmark-uptr->POS) * 10); /* wait again */ - uptr->CMD |= MT_READDONE; /* read is done */ + uptr->CMD |= MT_READDONE; /* read is done */ break; } sim_debug(DEBUG_CMD, dptr, "Read data @1 unit %02x cnt %04x ch %02x hwm %04x\n", unit, uptr->POS, ch, uptr->hwmark); - uptr->CMD &= ~MT_CMDMSK; /* clear the cmd */ - mt_busy[bufnum] &= ~1; /* set not busy */ + uptr->CMD &= ~MT_CMDMSK; /* clear the cmd */ + mt_busy[bufnum] &= ~1; /* set not busy */ chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* return end status */ } else { -// sim_debug(DEBUG_CMD, dptr, sim_debug(DEBUG_DETAIL, dptr, "Read data @2 unit %02x cnt %04x ch %02x hwm %04x\n", unit, uptr->POS, ch, uptr->hwmark); @@ -714,39 +752,39 @@ t_stat mt_srv(UNIT *uptr) sim_debug(DEBUG_CMD, dptr, "Read end of data unit %02x cnt %04x ch %02x hwm %04x\n", unit, uptr->POS, ch, uptr->hwmark); - uptr->CMD |= MT_READDONE; /* read is done */ - sim_activate(uptr, 40); /* wait again */ + uptr->CMD |= MT_READDONE; /* read is done */ + sim_activate(uptr, 40); /* wait again */ } else - sim_activate(uptr, 40); /* wait again */ + sim_activate(uptr, 40); /* wait again */ } break; - case MT_SETM: /* 0x83 */ /* set mode byte */ + case MT_SETM: /* 0x83 */ /* set mode byte */ sim_debug(DEBUG_CMD, dptr, "mt_srv cmd 0x83 SETM unit=%02x\n", unit); /* Grab data until channel has no more */ if (chan_read_byte(chsa, &ch)) { - if (uptr->POS > 0) { /* Only if data in record */ - reclen = uptr->hwmark; /* set record length */ - ch = mt_buffer[bufnum][0]; /* get the first byte read */ + if (uptr->POS > 0) { /* Only if data in record */ + reclen = uptr->hwmark; /* set record length */ + ch = mt_buffer[bufnum][0]; /* get the first byte read */ sim_debug(DEBUG_CMD, dptr, "Write mode data done unit %02x chars %02x mode %02x\n", unit, reclen, ch); /* put mode bits into byte 2 of SNS */ uptr->SNS = (uptr->SNS & 0xffff00ff) | (ch << 8); - uptr->POS = 0; /* no bytes anymore */ - uptr->CMD &= ~MT_CMDMSK; /* no cmd to do */ - mt_busy[bufnum] &= ~1; /* set not busy */ + uptr->POS = 0; /* no bytes anymore */ + uptr->CMD &= ~MT_CMDMSK; /* no cmd to do */ + mt_busy[bufnum] &= ~1; /* set not busy */ chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* return end status */ } } else { mt_buffer[bufnum][uptr->POS++] = ch; /* save the character read in */ sim_debug(DEBUG_CMD, dptr, "Write mode data in unit %02x POS %04x mode %02x\n", unit, uptr->POS, ch); - uptr->hwmark = uptr->POS; /* set high water mark */ - sim_activate(uptr, 40); /* wait time */ + uptr->hwmark = uptr->POS; /* set high water mark */ + sim_activate(uptr, 40); /* wait time */ } break; - case MT_WRITE: /* 0x01 */ /* write record */ + case MT_WRITE: /* 0x01 */ /* write record */ /* Check if write protected */ if (sim_tape_wrp(uptr)) { uptr->SNS |= SNS_CMDREJ; @@ -759,14 +797,14 @@ t_stat mt_srv(UNIT *uptr) /* Grab data until channel has no more */ if (chan_read_byte(chsa, &ch)) { - if (uptr->POS > 0) { /* Only if data in record */ + if (uptr->POS > 0) { /* Only if data in record */ reclen = uptr->hwmark; sim_debug(DEBUG_CMD, dptr, "Write unit=%02x Block %04x chars\n", unit, reclen); r = sim_tape_wrrecf(uptr, &mt_buffer[bufnum][0], reclen); uptr->POS = 0; uptr->CMD &= ~MT_CMDMSK; - mt_error(uptr, chsa, r, dptr); /* Record errors */ + mt_error(uptr, chsa, r, dptr); /* Record errors */ } } else { mt_buffer[bufnum][uptr->POS++] = ch; @@ -777,7 +815,7 @@ t_stat mt_srv(UNIT *uptr) sim_activate(uptr, 40); break; - case MT_RDBK: /* 0x0C */ /* Read Backwards */ + case MT_RDBK: /* 0x0C */ /* Read Backwards */ if (uptr->CMD & MT_READDONE) { uptr->CMD &= ~(MT_CMDMSK|MT_READDONE); mt_busy[bufnum] &= ~1; @@ -820,7 +858,7 @@ t_stat mt_srv(UNIT *uptr) } else { sim_debug(DEBUG_DETAIL, dptr, "Read data unit=%02x %04x %02x\n", unit, uptr->POS, ch); - if (uptr->POS == 0) { /* In IRG */ + if (uptr->POS == 0) { /* In IRG */ uptr->CMD &= ~MT_CMDMSK; mt_busy[bufnum] &= ~1; chan_end(chsa, SNS_CHNEND|SNS_DEVEND); @@ -829,7 +867,7 @@ t_stat mt_srv(UNIT *uptr) } break; - case MT_WTM: /* 0x93 */ /* Write tape filemark */ + case MT_WTM: /* 0x93 */ /* Write tape filemark */ if (uptr->POS == 0) { if (sim_tape_wrp(uptr)) { uptr->SNS |= SNS_CMDREJ; @@ -849,7 +887,7 @@ t_stat mt_srv(UNIT *uptr) } break; - case MT_BSR: /* 0x53 */ /* Backspace record */ + case MT_BSR: /* 0x53 */ /* Backspace record */ sim_debug(DEBUG_CMD, dptr, "mt_srv cmd 0x53 BSR unit %02x POS %04x\n", unit, uptr->POS); switch (uptr->POS ) { @@ -890,19 +928,19 @@ t_stat mt_srv(UNIT *uptr) case 3: /* EOF */ uptr->CMD &= ~(MT_CMDMSK); mt_busy[bufnum] &= ~1; - uptr->SNS |= SNS_FMRKDT; /* file mark detected */ + uptr->SNS |= SNS_FMRKDT; /* file mark detected */ chan_end(chsa, SNS_DEVEND|SNS_UNITEXP); break; case 4: /* BOT */ uptr->CMD &= ~(MT_CMDMSK); mt_busy[bufnum] &= ~1; - uptr->SNS |= SNS_LOAD; /* set BOT detected */ + uptr->SNS |= SNS_LOAD; /* set BOT detected */ chan_end(chsa, SNS_DEVEND|SNS_UNITEXP); break; } break; - case MT_BSF: /* 0x73 */ /* Backspace file */ + case MT_BSF: /* 0x73 */ /* Backspace file */ sim_debug(DEBUG_CMD, dptr, "mt_srv cmd 0x73 BSF unit %02x\n", unit); switch(uptr->POS) { case 0: @@ -932,20 +970,20 @@ t_stat mt_srv(UNIT *uptr) break; case 2: /* File Mark */ uptr->CMD &= ~(MT_CMDMSK); - uptr->SNS |= SNS_FMRKDT; /* file mark detected */ + uptr->SNS |= SNS_FMRKDT; /* file mark detected */ mt_busy[bufnum] &= ~1; chan_end(chsa, SNS_DEVEND); break; case 3: /* BOT */ uptr->CMD &= ~(MT_CMDMSK); mt_busy[bufnum] &= ~1; - uptr->SNS |= SNS_LOAD; /* set BOT */ + uptr->SNS |= SNS_LOAD; /* set BOT */ chan_end(chsa, SNS_DEVEND); break; } break; - case MT_FSR: /* 0x43 */ /* Advance record */ + case MT_FSR: /* 0x43 */ /* Advance record */ switch(uptr->POS) { case 0: sim_debug(DEBUG_CMD, dptr, "Skip rec entry unit=%02x ", unit); @@ -959,12 +997,12 @@ t_stat mt_srv(UNIT *uptr) r = sim_tape_sprecf(uptr, &reclen); if (r == MTSE_TMK) { uptr->POS = 3; - uptr->SNS |= SNS_FMRKDT; /* file mark detected */ + uptr->SNS |= SNS_FMRKDT; /* file mark detected */ sim_debug(DEBUG_CMD, dptr, "FSR MARK\n"); sim_activate(uptr, 50); } else if (r == MTSE_EOM) { uptr->POS = 4; - uptr->SNS |= SNS_EOT; /* set EOT status */ + uptr->SNS |= SNS_EOT; /* set EOT status */ sim_debug(DEBUG_CMD, dptr, "FSR EOT\n"); sim_activate(uptr, 50); } else { @@ -994,7 +1032,7 @@ t_stat mt_srv(UNIT *uptr) } break; - case MT_FSF: /* 0x63 */ /* advance filemark */ + case MT_FSF: /* 0x63 */ /* advance filemark */ switch(uptr->POS) { case 0: sim_debug(DEBUG_CMD, dptr, @@ -1008,11 +1046,11 @@ t_stat mt_srv(UNIT *uptr) r = sim_tape_sprecf(uptr, &reclen); if (r == MTSE_TMK) { uptr->POS++; - uptr->SNS |= SNS_FMRKDT; /* file mark detected */ + uptr->SNS |= SNS_FMRKDT; /* file mark detected */ sim_debug(DEBUG_CMD, dptr, "FSF EOF MARK sense %08x\n", uptr->SNS); sim_activate(uptr, 50); } else if (r == MTSE_EOM) { - uptr->SNS |= SNS_EOT; /* set EOT status */ + uptr->SNS |= SNS_EOT; /* set EOT status */ sim_debug(DEBUG_CMD, dptr, "FSF EOT sense %08x\n", uptr->SNS); uptr->POS+= 2; sim_activate(uptr, 50); @@ -1030,7 +1068,7 @@ t_stat mt_srv(UNIT *uptr) break; case 3: uptr->CMD &= ~(MT_CMDMSK); - uptr->SNS |= SNS_EOT; /* set EOT status */ + uptr->SNS |= SNS_EOT; /* set EOT status */ mt_busy[bufnum] &= ~1; sim_debug(DEBUG_CMD, dptr, "Skip file got EOT sense %08x unit %02x\n", uptr->SNS, unit); @@ -1039,7 +1077,7 @@ t_stat mt_srv(UNIT *uptr) } break; - case MT_ERG: /* 0xA3 */ /* Erace 3.5 in tape */ + case MT_ERG: /* 0xA3 */ /* Erace 3.5 in tape */ switch (uptr->POS) { case 0: if (sim_tape_wrp(uptr)) { @@ -1067,7 +1105,7 @@ t_stat mt_srv(UNIT *uptr) } break; - case MT_REW: /* 0x23 */ /* rewind tape */ + case MT_REW: /* 0x23 */ /* rewind tape */ if (uptr->POS == 0) { uptr->POS++; sim_debug(DEBUG_CMD, dptr, "Start rewind unit %02x\n", unit); @@ -1076,21 +1114,27 @@ t_stat mt_srv(UNIT *uptr) sim_debug(DEBUG_CMD, dptr, "Rewind complete unit %02x\n", unit); uptr->CMD &= ~(MT_CMDMSK); r = sim_tape_rewind(uptr); - uptr->SNS |= SNS_LOAD; /* set BOT */ + uptr->SNS |= SNS_LOAD; /* set BOT */ mt_busy[bufnum] &= ~1; chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* we are done dev|chan end */ } break; - case MT_RUN: /* 0x33 */ /* Rewind and unload tape */ + case MT_RUN: /* 0x33 */ /* Rewind and unload tape */ if (uptr->POS == 0) { uptr->POS++; mt_busy[bufnum] &= ~1; + sim_debug(DEBUG_CMD, dptr, "Start rewind/unload unit %02x\n", unit); sim_activate(uptr, 30000); } else { - sim_debug(DEBUG_CMD, dptr, "Unload unit=%02x\n", unit); - uptr->CMD &= ~(MT_CMDMSK); + sim_debug(DEBUG_CMD, dptr, "Unload unit=%02x\n", unit); + uptr->CMD &= ~(MT_CMDMSK); + uptr->SNS |= SNS_INTVENT; /* unit intervention required */ + uptr->SNS &= ~(SNS_RDY|SNS_ONLN); /* unit not online or rdy */ + uptr->SNS &= ~SNS_LOAD; /* reset BOT detected */ r = sim_tape_detach(uptr); +//?? set_devattn(chsa, SNS_DEVEND); /* ready int???? */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* we are done dev|chan end */ } break; } @@ -1104,11 +1148,11 @@ void mt_ini(UNIT *uptr, t_bool f) if (MT_DENS(uptr->dynflags) == 0) uptr->dynflags |= MT_DENS_6250 << UNIT_S_DF_TAPE; - uptr->CMD &= ~0xffff; /* clear out the flags but leave ch/sa */ - uptr->SNS = 0; /* clear sense data */ - uptr->SNS |= (SNS_RDY|SNS_ONLN|SNS_LOAD); /* set initial status */ - mt_busy[GET_DEV_BUF(dptr->flags)] = 0; /* set not busy */ - sim_cancel(uptr); /* cancel any timers */ + uptr->CMD &= ~0xffff; /* clear out the flags but leave ch/sa */ + uptr->SNS = 0; /* clear sense data */ + uptr->SNS |= (SNS_RDY|SNS_ONLN|SNS_LOAD); /* set initial status */ + mt_busy[GET_DEV_BUF(dptr->flags)] = 0; /* set not busy */ + sim_cancel(uptr); /* cancel any timers */ sim_debug(DEBUG_EXP, dptr, "MT init device %s unit %02x\n", dptr->name, GET_UADDR(uptr->CMD)); } @@ -1118,10 +1162,9 @@ uint16 mt_rschnlio(UNIT *uptr) { DEVICE *dptr = get_dev(uptr); uint16 chsa = GET_UADDR(uptr->CMD); int cmd = uptr->CMD & MT_CMDMSK; -// int unit = (uptr - mt_unit); /* unit 0 */ sim_debug(DEBUG_EXP, dptr, "mt_rschnl chsa %04x cmd = %02x\n", chsa, cmd); - mt_ini(uptr, 0); /* reset the unit */ + mt_ini(uptr, 0); /* reset the unit */ return SCPE_OK; } @@ -1136,64 +1179,65 @@ t_stat mt_reset(DEVICE *dptr) /* attach the specified file to the tape device */ t_stat mt_attach(UNIT *uptr, CONST char *file) { - uint16 chsa = GET_UADDR(uptr->CMD); /* get address of mt device */ - CHANP *chp = find_chanp_ptr(chsa); /* get channel prog pointer */ - DEVICE *dptr = get_dev(uptr); /* get device pointer */ + uint16 chsa = GET_UADDR(uptr->CMD); /* get address of mt device */ + CHANP *chp = find_chanp_ptr(chsa); /* get channel prog pointer */ + DEVICE *dptr = get_dev(uptr); /* get device pointer */ t_stat r; DIB *dibp = 0; /* mount the specified file to the MT */ if ((r = sim_tape_attach(uptr, file)) != SCPE_OK) { sim_debug(DEBUG_EXP, dptr, "mt_attach ERROR filename %s status %08x\n", file, r); - return r; /* report any error */ + return r; /* report any error */ } sim_debug(DEBUG_EXP, dptr, "mt_attach complete filename %s\n", file); - uptr->CMD &= ~0xffff; /* clear out the flags but leave ch/sa */ - uptr->POS = 0; /* clear position data */ - uptr->SNS = 0; /* clear sense data */ + uptr->CMD &= ~0xffff; /* clear out the flags but leave ch/sa */ + uptr->POS = 0; /* clear position data */ + uptr->SNS = 0; /* clear sense data */ + uptr->SNS |= SNS_ONLN; /* 0x40 Drive Online */ /* check for valid configured tape */ /* must have valid DIB and Channel Program pointer */ - dibp = (DIB *)dptr->ctxt; /* get the DIB pointer */ + dibp = (DIB *)dptr->ctxt; /* get the DIB pointer */ if ((dib_unit[chsa] == NULL) || (dibp == NULL) || (chp == NULL)) { sim_debug(DEBUG_CMD, dptr, "ERROR===ERROR\nMT device %s not configured on system, aborting\n", dptr->name); printf("ERROR===ERROR\nMT device %s not configured on system, aborting\n", dptr->name); - detach_unit(uptr); /* detach if error */ - return SCPE_UNATT; /* error */ + detach_unit(uptr); /* detach if error */ + return SCPE_UNATT; /* error */ } - set_devattn(chsa, SNS_DEVEND); /* ready int???? */ - return SCPE_OK; /* return good status */ + set_devattn(chsa, SNS_DEVEND); /* ready int???? */ + return SCPE_OK; /* return good status */ } /* detach the MT device and unload any tape */ t_stat mt_detach(UNIT *uptr) { - DEVICE *dptr = get_dev(uptr); /* get device pointer */ + DEVICE *dptr = get_dev(uptr); /* get device pointer */ sim_debug(DEBUG_EXP, dptr, "mt_detach\n"); - uptr->CMD &= ~0xffff; /* clear out the flags but leave ch/sa */ - uptr->POS = 0; /* clear position data */ - uptr->SNS = 0; /* clear sense data */ + uptr->CMD &= ~0xffff; /* clear out the flags but leave ch/sa */ + uptr->POS = 0; /* clear position data */ + uptr->SNS = 0; /* clear sense data */ return sim_tape_detach(uptr); } /* boot from the specified tape unit */ t_stat mt_boot(int32 unit_num, DEVICE *dptr) { - UNIT *uptr = &dptr->units[unit_num]; /* find tape unit pointer */ + UNIT *uptr = &dptr->units[unit_num]; /* find tape unit pointer */ sim_debug(DEBUG_EXP, dptr, "MT Boot dev/unit %04x\n", GET_UADDR(uptr->CMD)); - if ((uptr->flags & UNIT_ATT) == 0) { /* Is MT device already attached? */ + if ((uptr->flags & UNIT_ATT) == 0) { /* Is MT device already attached? */ sim_debug(DEBUG_EXP, dptr, "MT Boot attach error dev/unit %04x\n", GET_UADDR(uptr->CMD)); - return SCPE_UNATT; /* not attached, return error */ + return SCPE_UNATT; /* not attached, return error */ } - SPAD[0xf4] = GET_UADDR(uptr->CMD); /* put boot device chan/sa into spad */ - SPAD[0xf8] = 0xF000; /* show as F class device */ + SPAD[0xf4] = GET_UADDR(uptr->CMD); /* put boot device chan/sa into spad */ + SPAD[0xf8] = 0xF000; /* show as F class device */ - uptr->CMD &= ~0xffff; /* clear out old status */ + uptr->CMD &= ~0xffff; /* clear out old status */ return chan_boot(GET_UADDR(uptr->CMD), dptr); /* boot the ch/sa */ } diff --git a/SEL32/sel32_scfi.c b/SEL32/sel32_scfi.c index 452a81d..748615d 100644 --- a/SEL32/sel32_scfi.c +++ b/SEL32/sel32_scfi.c @@ -608,8 +608,7 @@ loop: return 1; /* if none, error */ } -// sim_debug(DEBUG_XIO, dptr, - sim_debug(DEBUG_DETAIL, dptr, + sim_debug(DEBUG_XIO, dptr, "scfi_iocl @%06x before start_cmd chan %04x status %04x count %04x SNS %08x\n", chp->chan_caw, chan, chp->chan_status, chp->ccw_count, uptr->u5); @@ -619,8 +618,7 @@ loop: chp->chan_status = (chp->chan_status & 0xff00) | devstat; chp->chan_info &= ~INFO_SIOCD; /* show not first IOCD in channel prog */ -// sim_debug(DEBUG_XIO, dptr, - sim_debug(DEBUG_DETAIL, dptr, + sim_debug(DEBUG_XIO, dptr, "scfi_iocl @%06x after start_cmd chan %04x status %08x count %04x\n", chp->chan_caw, chan, chp->chan_status, chp->ccw_count); @@ -651,16 +649,14 @@ loop: if (chp->chan_status & (STATUS_DEND|STATUS_CEND)) { uint16 chsa = GET_UADDR(uptr->u3); /* get channel & sub address */ chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* show I/O complete */ -// sim_debug(DEBUG_XIO, dptr, - sim_debug(DEBUG_DETAIL, dptr, + sim_debug(DEBUG_XIO, dptr, "scfi_iocl @%06x FIFO #%1x cmd complete chan %04x status %04x count %04x\n", chp->chan_caw, FIFO_Num(chsa), chan, chp->chan_status, chp->ccw_count); } } /* the device processor returned OK (0), so wait for I/O to complete */ /* nothing happening, so return */ -// sim_debug(DEBUG_XIO, dptr, - sim_debug(DEBUG_DETAIL, dptr, + sim_debug(DEBUG_XIO, dptr, "scfi_iocl @%06x return, chan %04x status %04x count %04x irq_pend %1x\n", chp->chan_caw, chan, chp->chan_status, chp->ccw_count, irq_pend); return 0; /* good return */ @@ -673,8 +669,7 @@ uint16 scfi_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) int32 unit = (uptr - dptr->units); CHANP *chp = find_chanp_ptr(chsa); /* find the chanp pointer */ -// sim_debug(DEBUG_CMD, dptr, - sim_debug(DEBUG_DETAIL, dptr, + sim_debug(DEBUG_CMD, dptr, "scfi_startcmd chsa %04x unit %02x cmd %02x CMD %08x\n", chsa, unit, cmd, uptr->CMD); if ((uptr->flags & UNIT_ATT) == 0) { /* unit attached status */ @@ -690,8 +685,7 @@ uint16 scfi_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) return SNS_BSY; } uptr->SNS2 |= SNS_USEL; /* unit selected */ -// sim_debug(DEBUG_CMD, dptr, - sim_debug(DEBUG_DETAIL, dptr, + sim_debug(DEBUG_CMD, dptr, "scfi_startcmd CMD continue unit=%02x cmd %02x iocla %06x cnt %04x\n", unit, cmd, chp->chan_caw, chp->ccw_count); @@ -769,8 +763,7 @@ uint16 scfi_haltio(UNIT *uptr) { int cmd = uptr->CMD & DSK_CMDMSK; CHANP *chp = find_chanp_ptr(chsa); /* find the chanp pointer */ -// sim_debug(DEBUG_EXP, dptr, - sim_debug(DEBUG_DETAIL, dptr, + sim_debug(DEBUG_EXP, dptr, "scfi_haltio enter chsa %04x cmd = %02x\n", chsa, cmd); /* terminate any input command */ @@ -778,8 +771,7 @@ uint16 scfi_haltio(UNIT *uptr) { /* status must not have an error bit set */ /* otherwise, UTX will panic with "bad status" */ if ((uptr->CMD & DSK_CMDMSK) != 0) { /* is unit busy */ -// sim_debug(DEBUG_CMD, dptr, - sim_debug(DEBUG_DETAIL, dptr, + sim_debug(DEBUG_CMD, dptr, "scfi_haltio HIO chsa %04x cmd = %02x ccw_count %02x\n", chsa, cmd, chp->ccw_count); /* stop any I/O and post status and return error status */ @@ -787,16 +779,14 @@ uint16 scfi_haltio(UNIT *uptr) { uptr->CMD &= LMASK; /* make non-busy */ uptr->SNS2 |= (SNS_ONC|SNS_UNR); /* on cylinder & ready */ sim_cancel(uptr); /* clear the input timer */ -// sim_debug(DEBUG_CMD, dptr, - sim_debug(DEBUG_EXP, dptr, + sim_debug(DEBUG_CMD, dptr, "scfi_haltio HIO I/O stop chsa %04x cmd = %02x\n", chsa, cmd); chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* force end */ return SCPE_IOERR; } uptr->CMD &= LMASK; /* make non-busy */ uptr->SNS2 |= (SNS_ONC|SNS_UNR); /* on cylinder & ready */ -// sim_debug(DEBUG_CMD, dptr, - sim_debug(DEBUG_DETAIL, dptr, + sim_debug(DEBUG_CMD, dptr, "scfi_haltio HIO I/O not busy chsa %04x cmd = %02x\n", chsa, cmd); return SCPE_OK; /* not busy */ } @@ -820,8 +810,7 @@ t_stat scfi_srv(UNIT *uptr) uint8 buf[1024]; uint8 buf2[1024]; -// sim_debug(DEBUG_CMD, dptr, - sim_debug(DEBUG_DETAIL, dptr, + sim_debug(DEBUG_CMD, dptr, "scfi_srv entry unit %02x CMD %08x chsa %04x count %04x %x/%x/%x \n", unit, uptr->CMD, chsa, chp->ccw_count, STAR2CYL(uptr->CHS), (uptr->CHS >> 8)&0xff, (uptr->CHS&0xff)); @@ -834,8 +823,7 @@ t_stat scfi_srv(UNIT *uptr) } } -// sim_debug(DEBUG_CMD, dptr, - sim_debug(DEBUG_DETAIL, dptr, + sim_debug(DEBUG_CMD, dptr, "scfi_srv cmd=%02x chsa %04x count %04x\n", cmd, chsa, chp->ccw_count); switch (cmd) { @@ -1063,7 +1051,6 @@ t_stat scfi_srv(UNIT *uptr) /* we have already seeked to the required sector */ /* we do not need to seek again, so move on */ chan_end(chsa, SNS_DEVEND|SNS_CHNEND); -// return SCPE_OK; break; } else { /* we have wasted enough time, we are there */ @@ -1546,7 +1533,6 @@ int scfi_format(UNIT *uptr) { uint32 laddr = CAP(type) - 1; /* last sector of disk */ /* make up dummy defect map */ -// uint32 dmap[4] = {0xf0000000 | (cap-1), 0x8a000000 | daddr, uint32 dmap[4] = {0xf0000000 | (cap-1), 0x8a000000, 0x9a000000 | (cap-1), 0xf4000000}; @@ -1640,9 +1626,7 @@ t_stat scfi_attach(UNIT *uptr, CONST char *file) /* get sector address of utx diag map (DMAP) track 0 pointer */ /* put data = 0xf0000000 + (cyl-1), 0x8a000000 + daddr, */ /* 0x9a000000 + (cyl-1), 0xf4000000 */ -// int32 daddr = (CYL(type)-4) * SPC(type) + (HDS(type)-2) * SPT(type); /* defect map */ -// uint32 dmap[4] = {0xf0000000 | (CAP(type)-1), 0x8a000000 | daddr, uint32 dmap[4] = {0xf0000000 | (CAP(type)-1), 0x8a000000, 0x9a000000 | (CAP(type)-1), 0xf4000000}; @@ -1687,7 +1671,8 @@ t_stat scfi_attach(UNIT *uptr, CONST char *file) printf("SCFI Disk attach ftell failed s=%06d\r\n", s); goto fmt; /* not setup, go format */ } - sim_debug(DEBUG_CMD, dptr, "SCFI Disk attach ftell value s=%06d b=%06d CAP %06d\n", s/ssize, s, CAP(type)); + sim_debug(DEBUG_CMD, dptr, + "SCFI Disk attach ftell value s=%06d b=%06d CAP %06d\n", s/ssize, s, CAP(type)); printf("SCFI Disk attach ftell value s=%06d b=%06d CAP %06d\r\n", s/ssize, s, CAP(type)); if (((int)s/(int)ssize) < ((int)CAP(type))) { /* full sized disk? */ @@ -1706,8 +1691,10 @@ t_stat scfi_attach(UNIT *uptr, CONST char *file) } s = ftell(uptr->fileref); /* get current file position */ sim_debug(DEBUG_CMD, dptr, - "SCFI Disk attach MPX 1.X file extended & sized secs %06d bytes %06d\n", s/ssize, s); - printf("SCFI Disk attach MPX 1.X file extended & sized secs %06d bytes %06d\r\n", s/ssize, s); + "SCFI Disk attach MPX 1.X file extended & sized secs %06d bytes %06d\n", + s/ssize, s); + printf("SCFI Disk attach MPX 1.X file extended & sized secs %06d bytes %06d\r\n", + s/ssize, s); } /* seek last sector of disk */ diff --git a/SEL32/sel32_scsi.c b/SEL32/sel32_scsi.c index da58416..050ac95 100644 --- a/SEL32/sel32_scsi.c +++ b/SEL32/sel32_scsi.c @@ -320,9 +320,6 @@ UNIT sba_unit[] = { {UDATA(&scsi_srv, UNIT_SCSI|SET_TYPE(0), 0), 0, UNIT_ADDR(0x7608)}, /* 1 */ }; -//DIB sba_dib = {scsi_preio, scsi_startcmd, NULL, NULL, NULL, scsi_ini, -//sba_unit, sba_chp, NUM_UNITS_SCSI, 0x0f, 0x0400, 0, 0, 0}; - DIB sba_dib = { scsi_preio, /* uint16 (*pre_io)(UNIT *uptr, uint16 chan)*/ /* Pre Start I/O */ scsi_startcmd, /* uint16 (*start_cmd)(UNIT *uptr, uint16 chan, uint8 cmd)*/ /* Start command */ @@ -481,7 +478,6 @@ uint16 scsi_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) uptr->CMD |= cmd; /* save cmd */ sim_debug(DEBUG_CMD, dptr, "scsi_startcmd starting disk seek r/w cmd %02x chsa %04x\n", cmd, chsa); -// sim_activate(uptr, 20); /* start things off */ sim_activate(uptr, 100); /* start things off */ return 0; break; @@ -491,7 +487,6 @@ uint16 scsi_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) cmd, chsa, uptr->SNS); if (uptr->SNS & 0xff) /* any other cmd is error */ return SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK; -// sim_activate(uptr, 20); /* start things off */ sim_activate(uptr, 100); /* start things off */ return SNS_CHNEND|SNS_DEVEND; } @@ -637,7 +632,6 @@ t_stat scsi_srv(UNIT *uptr) chan_write_byte(chsa, &ch); /* bytes 4 - mode reg, byte 0 of SNS */ -// ch = (uptr->SNS >> 24) & 0xff; /* return the sense data */ /* skip the TCMD bit */ ch = (uptr->SNS >> 24) & 0xfe; /* return the sense data */ sim_debug(DEBUG_DETAIL, dptr, "scsi_srv sense unit=%02x 1 %02x\n", @@ -681,7 +675,6 @@ t_stat scsi_srv(UNIT *uptr) sim_debug(DEBUG_CMD, dptr, "scsi_srv seek over on cylinder unit=%02x %04x %04x\n", unit, uptr->STAR, uptr->CHS); uptr->CHS = uptr->STAR; /* we are there */ -// sim_activate(uptr, 10); sim_activate(uptr, 40); break; } @@ -1263,19 +1256,8 @@ read_cap: /* merge point from TCMD process /* mema has IOCD word 1 contents. */ /* len has the byte count from IOCD wd2 */ - len = chp->ccw_count; /* TCMD command count */ -#ifdef NOTNOW - if (len != 36) { - /* we have invalid count, error, bail out */ - uptr->CMD &= LMASK; /* remove old status bits & cmd */ - uptr->SNS |= SNS_CMDREJ|SNS_EQUCHK; - chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); - break; - } -#endif - for (i=0; i < len; i++) { if (chan_read_byte(chsa, &buf[i])) { /* we have error, bail out */ @@ -1319,8 +1301,7 @@ read_cap: /* merge point from TCMD process return SNS_CHNEND|STATUS_PCHK; break; } -// sim_debug(DEBUG_CMD, dptr, - sim_debug(DEBUG_DETAIL, dptr, + sim_debug(DEBUG_CMD, dptr, "scsi_srv done cmd %02x chsa %04x count %04x\n", cmd, chsa, chp->ccw_count); return SCPE_OK; } diff --git a/SEL32/sel32_sys.c b/SEL32/sel32_sys.c index c814134..faa84d1 100644 --- a/SEL32/sel32_sys.c +++ b/SEL32/sel32_sys.c @@ -1024,8 +1024,6 @@ t_stat fprint_sym (FILE *of, t_addr addr, t_value *val, UNIT *uptr, int32 sw) rdx = 16; /* hex */ if (sw & SWMASK ('M')) { /* machine base mode? */ -// sw &= ~ SWMASK('F'); /* Can't do F and M at same time */ -// sw &= ~ SWMASK('W'); /* Can't do W and M at same time */ sw &= ~ SWMASK('B'); /* Can't do B and M at same time */ sw &= ~ SWMASK('C'); /* Can't do C and M at same time */ if (addr & 0x02) diff --git a/SEL32/taptools/README.md b/SEL32/taptools/README.md index e7fdb4f..6bce0e1 100644 --- a/SEL32/taptools/README.md +++ b/SEL32/taptools/README.md @@ -25,55 +25,55 @@ cutostap - This program scans a metadata .tap file and copies files user sdt tape with files following the sdt image. command: cutostap stdout - input - stdin file to be written with sdt image diskload - This program reads an MPX load module and stores it into - simulated diskfile. The MPX-1.x SMD entry for the file + simulated diskfile. The MPX 1.X SMD entry for the file is entered into the SMD for the file. Will not work for - MPX 3.x file systems. + MPX 3.X file systems. command: diskload -la program diskfile option -a - add filename to diskfile option -l - list files in diskfile SMD, ignore filename - input - filename - file to copy to system disk - - diskfile - simulated system disk - output - modified system disk + input - filename - file to copy to system disk + - diskfile - simulated system disk + output - modified system disk filelist - This program scans a metadata .tap file and prints the file count and sizes. Used to determine the file format contained in the metadata .tap file. command: filelist stdout - input - stdin stdout input - file.tap file to dump output - stdout filelist and sizes output - directory/files extracted to current directory -mkfmtape - This program creates an MPX 1.x filemgr save tape. The - tape can then be used to restore files to the MPX-1.X +mkfmtape - This program creates an MPX 1.X filemgr save tape. The + tape can then be used to restore files to the MPX 1.x system. The output will be in SIMH simulated .tap format. command: mkfmtape opts output.tap file1 file2 ... input - list of filename to save to tape. output - output.tap a tap formatted file. options - -p = file type 0xca for programs - - -t = ascii text file 0xee - - -l = library/directory file 0xff - - -o = other 0x00 + - -t = ASCII text file type 0xee + - -l = library/directory file type 0xff + - -o = other type 0x00 - -a = append entries to current file - -u = username (directory) @@ -89,9 +89,9 @@ mkvmtape - This program reads MPX files and stores them into a output - volmtape file, file list to stdout options - -p = file type 0xca for programs - - -t = ascii text file 0xee - - -l = library/directory file 0xff - - -o = other 0x00 + - -t = ASCII text file type 0xee + - -l = library/directory file type 0xff + - -o = other type 0x00 - -a = append entries to current file - -u = username (username) - -d = dirname (directory) @@ -99,7 +99,6 @@ mkvmtape - This program reads MPX files and stores them into a - -b = bootfile name - -i = system image file - -j = j.vfmt filename - 04/11/2020 update for mpx3.x mkdiagtape.c - This program extracts the diag command file (file 2) from a diagnostic tape in .tap format and replaces it @@ -132,7 +131,7 @@ diagcopy - This program reads a SEL .tap diagnostic boot tape and splits the contents into multiple files. The first tape record is 204 bytes of boot code and is put into the file bootcode. The following records in the file contains the diagnostic - overlay program (DOL) and are in 7680 byte block. The last + overlay program (DOL) and are in 7680 byte blocks. The last record can be <= 7680 bytes. The data is put into the file dolfile. The 2nd file on the tape contains the diagnostic auto execute file. It is a MPX blocked file where the first @@ -152,21 +151,21 @@ diagcopy - This program reads a SEL .tap diagnostic boot tape and splits tapdump - This program reads a metadata .tap file and prints a side by side hexdump of the file contents. The records are - displayed as 256 byte chuncks. After each record if 256 - bytes are displayed, hitting will continue dump, - hitting will terminate the display, and hitting + displayed as 256 byte chuncks. After each record of 256 + bytes are displayed, hitting C/R will continue dumping, + hitting 'q' will terminate the display, and hitting 's' will skip to the next file on the simulated tape. command: tapdump stdout - input - stdin stdout input - file.tap file to scan output - stdout filelist and sizes -volmcopy - This program reads a MPX 3.x volmgr save tape. The tape +volmcopy - This program reads a MPX 3.X volmgr save tape. The tape must contain a volmgr save image with 6144 byte records - containing a list of saved files. Followed by directdory + containing a list of saved files. Followed by directory entries of 1536 bytes and finally file data of 1 to 8 768 byte records. Files larger than 6144 bytes will be output as modulo 6144 bytes. There is an EOF after each file @@ -201,7 +200,7 @@ volmcopy - This program reads a MPX 3.x volmgr save tape. The tape current directory for each different directory. Within each directory each file contained on the tape is extracted and written as binary data to the named file. The .tap - file MUST be a volmgr save tape and not a MPX-1.x SDT/save + file MUST be a volmgr save tape and not a MPX 1.X SDT/save tape. command: fmgrcopy file.tap >stdout @@ -211,51 +210,51 @@ volmcopy - This program reads a MPX 3.x volmgr save tape. The tape General utilities for MPX -ddump - Create a sys by side ascii dump of a file. Same operation +ddump - Create a side by side ASCII dump of a file. Same operation as the DDUMP utility in MPX. 256 bytes are displayed at - a time. Hitting will continue to next 256 bytes. A + a time. Hitting C/R will continue to next 256 bytes. A hex address can be input to display data at a given offset - in the file. Optionall, the file data can be modified. + in the file. Optionally, the file data can be modified. command: ddump -r filename option - -r means open file read only input - filename file to read - output - side by size ascii dump of file + output - side by size ASCII dump of file -deblk - read and convert mpx blocked ifile to unblocked unix file +deblk - read and convert a MPX blocked file to unblocked UNIX file format. Compressed and uncompressed files records can be - read. Output is an ascii string with '\n' termination. + read. Output is an ASCII string with '\n' termination. command: deblk [filename] input - filename or if non specified, stdin - output - ascii sting to stdout + output - ASCII sting to stdout -mpxblk - Create an MPX blocked file from a '\n' terminated ascii +mpxblk - Create an MPX blocked file from a '\n' terminated ASCII character string file. Trailing blanks are not deleted from the source file. Max line size is 254 bytes. command: mpxblk fileout - input - read ascii file from stdin - output - write mpx blocked file to stdout + input - read a '\n' terminated ASCII file from stdin + output - write MPX blocked file to stdout -renum - Create a numbered file from a '\n' terminated ascii file. - The input file is assumed to be a standard unix file. The +renum - Create a numbered file from a '\n' terminated ASCII file. + The input file is assumed to be a standard UNIX file. The input lines are truncated or expaned to lines of 72 chars. - A line number in the form of XXXX.000 are appended to + A line number in the form of XXXX.000 is appended to create 80 char '\n' terminated lines. command: renum fileout - input - read ascii file from stdin - output - write numbered ascii file to stdout + input - read ASCII file from stdin + output - write numbered ASCII file to stdout -small - Remove line numbers and trailing blanks from an ascii '\n' +small - Remove line numbers and trailing blanks from an ASCII '\n' terminated file. Lines are terminated at 72 chars and then stripped of trailing blanks. Output is '\n' terminated - ascii files. + ASCII files. command: small fileout - input - read ascii file from stdin - output - write stripped ascii file to stdout + input - read ASCII file from stdin + output - write stripped ASCII file to stdout James C. Bevier -08/21/2020 +02/15/2021 diff --git a/SEL32/taptools/deblk.c b/SEL32/taptools/deblk.c index 5964949..d41534c 100644 --- a/SEL32/taptools/deblk.c +++ b/SEL32/taptools/deblk.c @@ -154,24 +154,23 @@ char *argv[]; * This function computes and checks the checksum of a compressed file */ int checksum(buf) -char *buf; +unsigned char *buf; { int i = 0; -// unsigned int ccs = 0; /*zero checksum */ short int ccs = 0; /*zero checksum */ unsigned int rcs = (((buf[2] << 8) & 0xff00) | (buf[3] & 0xff)); /* get checksum */ - int cnt = buf[1]; /* record count */ -// fprintf(stderr, "checksum data %x %x %x %x\n", buf[0], buf[1], buf[2], buf[3]); + int cnt = buf[1] & 0xff; /* record count */ +//fprintf(stderr, "checksum cnt %x data %x %x %x %x %x %x %x %x\n", +// cnt, buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7]); while (cnt > 0) { -// unsigned int v = buf[i+6]; - short v = buf[i+6] & 0xff; + unsigned short v = buf[i+6] & 0xff; ccs += v; /* add the byte */ -// fprintf(stderr, "checksum cnt %x val %x sum %x\n", i, v, ccs); +//fprintf(stderr, "checksum cnt %x val %x sum %x\n", i, v, ccs); i++; /* bump address */ cnt--; /* reduce count */ } -// fprintf(stderr, "checksum size %x read %x calc %x\n", buf[1], rcs, ccs); +//fprintf(stderr, "checksum size %x read %x calc %x\n", buf[1], rcs, ccs); if (ccs == rcs) return 0; /* return OK */ return 1; /* return error */ @@ -241,18 +240,25 @@ int getb(fp) FILE *fp; { int c; + static int goteof = 0; /* file is unblocked, get next record */ + if (goteof) { + goteof = 0; +//fprintf(stderr, "getb - returning EOF ubdc=%x\n", ubdc); + return (-1); /* this means eof */ + } + if (ubdp < ubdc) /* is count exhausted */ + c = si[ubdp++] & 0xff; /* copy char */ if (ubdp >= ubdc) { /* is count exhausted */ /* need to read next block, if not first time */ /* we need a new buffer */ /* read in 768 byte block of the file */ if ((ubdc = fread(si, 1, BLKSIZE, fp)) <= 0) - return (-1); /* this means eof */ -//fprintf(stderr, "getb - read unblocked file ubdc=%x\n", ubdc); + goteof = 1; /* this means eof */ +//fprintf(stderr, "getb - read unblocked file goteof %x ubdc=%x\n", goteof, ubdc); ubdp = 0; } - c = si[ubdp++] & 0xff; /* copy char */ return (c); } @@ -262,7 +268,7 @@ FILE *fp; unsigned char s[]; int lim; { - int c, i, cc, rc = 0; + int c, i, cc, bc = 0, rc = 0; /* see how we are to process data */ if (filetype & blocked) { @@ -312,49 +318,64 @@ newbuf: if (filetype & compress) { cc = 120; rc = 0; + bc = 0; while ((c = getb(fp)) != -1) { - /* skip any optional newline from previous record */ -// if ((rc == 0) && (c == '\n')) -// continue; /* make sure this is a compressed record */ if ((rc == 0) && ((c & 0x9f) != 0x9f)) { - fprintf(stderr, "getloi - unblocked compressed file read error %x\n", c); + fprintf(stderr, "getloi - unblocked compressed file read error %x rc %x\n", c, rc); return (0); /* this means error */ } if (rc == 1) cc = c + 6; /* get 'real' record count */ s[rc++] = c; /* save the char */ - if (rc == cc) -// if (rc == 120) /* compressed is always 120 char buffers */ + + if (rc == cc) /* compressed record is always <= 120 char buffers */ break; /* done */ } if (c == -1) return (0); /* this means EOF */ /* skip any extra chars from short records */ - while ((c = getb(fp)) != '\n') - ; + bc = rc; + while ((s[0] != 0x9f) && (bc < 120)) { + if ((c = getb(fp)) == -1) + return (0); /* this means EOF */ + s[bc++] = c; /* fill extra chars */ +//fprintf(stderr, "getloi - filling extra chars with char %x bc %x\n", c, bc); + } + /* next char should be bf/9f */ + if ((si[ubdp] & 0x9f) != 0x9f) { /* copy char */ + if ((c = getb(fp)) == -1) { +//fprintf(stderr, "getloi skipping exit char %0x at end of line, next %x s[0] %0x\n", c, si[ubdp], s[0]); + if (s[0] != 0x9f) + return (0); /* this means EOF */ + } +//fprintf(stderr, "getloi skipping char %0x at end of line, next %x s[0] %0x\n", c, si[ubdp], s[0]); + } + +//fprintf(stderr, "getloi unblked comp read done rc %x cc %x s[0] %x s[rc-1] %x next %x\n", +//rc, cc, s[0], s[rc-1], si[ubdp]); /* checksum the record */ if (checksum(s)) { fprintf(stderr, "getloi - unblocked compressed file checksum error\n"); //fprintf(stderr, "getloi A unblocked compressed read return rc=%x cc=%x %x %x\n", rc, cc, s[0], s[rc-1]); //fprintf(stderr, "getloi C unblocked compressed read return %x ubdc %x ubdp %x\n", rc, ubdc, ubdp); - return (0); /* this means error */ + return (0); /* this means error */ } //fprintf(stderr, "getloi B unblocked compressed read return rc=%x cc=%x %x\n", rc, cc, s[1]); - return (rc); /* return data count */ + return (rc); /* return data count */ } /* file is uncompressed, so copy UNIX records */ while ((c = getb(fp)) != -1) { - s[rc++] = c; /* save the char */ + s[rc++] = c; /* save the char */ if (c == 0x0a) { //fprintf(stderr, "getloi C unblocked compressed read return %x ubdc %x ubdp %x\n", rc, ubdc, ubdp); s[rc++] = 0; /* terminate the line */ return (rc); /* return data */ } } - return (0); /* EOF */ + return (0); /* EOF */ } return (0); #ifdef JUNK @@ -405,6 +426,7 @@ unsigned char *s; } unsigned char line[BUFSIZ]; +unsigned char line2[BUFSIZ]; int cmpop = 0; int cmpflg = 0; int bcnt = 0; @@ -518,7 +540,7 @@ int n; } } if ((filetype & compress) && !cmpop) { /* see if we tested for compressed */ - cmpop = 1; /* set comp tested flag */ + cmpop = 1; /* set compresse tested flag */ /* read in the first record */ if ((recl = getloi(fp, line, BUFSIZ)) == 0) return (0); /* this means eof */ @@ -541,7 +563,7 @@ int n; if ((recl = getloi(fp, line, BUFSIZ)) == 0) return (0); /* this means eof */ linadrs = line; -//fprintf(stderr, "rbl re18 - read compressed record cnt %x %x\n", bcnt, linadrs[0]); +//fprintf(stderr, "rbl re18 - read compressed record recl %x cnt %x 1st %x\n", recl, bcnt, linadrs[0]); if ((*linadrs & 0x9f) != 0x9f) /* is this valid rec */ return (EOF); /* error if not */ bcnt = linadrs[1]; /* set record count */ @@ -553,6 +575,7 @@ int n; if (i = *bptr++) { /* next buffer pointer */ if (i == 0xff) goto re60; /* if eol, get out */ + /* insert the required number of blanks */ while (i--) { if (count < n) { *buf++ = ' '; /* put blank in buffer */ @@ -565,6 +588,8 @@ int n; /* get character count */ if (i = *bptr++) { /* next buffer pointer */ +/*try*/ if (i == 0xff) +/*0216*/ goto re60; /* if eol, get out */ while (i--) { if (count < n) *buf++ = *bptr; /* put char in buffer */ @@ -617,6 +642,6 @@ int n; buf[count++] = '\n'; buf[count] = '\0'; } -//fprintf(stderr, "rbl - read return cnt %x %s\n", count, line); +//fprintf(stderr, "rbl - read return cnt %x\n", count); return (count); } diff --git a/SEL32/taptools/renum.c b/SEL32/taptools/renum.c index 593a3c3..cc085a2 100644 --- a/SEL32/taptools/renum.c +++ b/SEL32/taptools/renum.c @@ -34,7 +34,9 @@ int lim; i = 72; for (; i<72; i++) s[i] = ' '; - sprintf(line, "%04d.000", ln++); +// sprintf(line, "%04d.000", ln++); + sprintf(line, "%04d.%01d00", ln/10, ln%10); + ln++; for (j=0; j<8; j++) s[72+j] = line[j]; s[80] = '\n';