diff --git a/SEL32/README.md b/SEL32/README.md index f7a56ae..6ecb25e 100644 --- a/SEL32/README.md +++ b/SEL32/README.md @@ -93,5 +93,5 @@ Other MPX verion support: disk image of a bootable system.. James C. Bevier -04/21/2020 +05/19/2020 diff --git a/SEL32/sel32_chan.c b/SEL32/sel32_chan.c index e8ea6a7..6e7fbd2 100644 --- a/SEL32/sel32_chan.c +++ b/SEL32/sel32_chan.c @@ -118,6 +118,7 @@ t_stat set_dev_addr(UNIT *uptr, int32 val, CONST char *cptr, void *desc); t_stat show_dev_addr(FILE *st, UNIT *uptr, int32 v, CONST void *desc); DEVICE *get_dev(UNIT *uptr); void store_csw(CHANP *chp); +int16 post_csw(CHANP *chp, uint32 rstat); /* FIFO support */ /* These are FIFO queues which return an error when full. @@ -137,20 +138,16 @@ void store_csw(CHANP *chp); /* add an entry to the FIFO */ int32 FIFO_Put(uint16 chsa, uint32 entry) { -//#define OLD_CHAN -#ifdef OLD_CHAN - DIB *dibp = dib_unit[chsa & 0x7f00]; /* get DIB pointer for channel */ -#else DIB *dibp = dib_chan[get_chan(chsa)]; /* get DIB pointer for channel */ if (dibp == NULL) { sim_debug(DEBUG_EXP, &cpu_dev, - "FIFO_Put NULL dib ptr for chsa %04x\n", chsa); + "FIFO_Put ERR NULL dib ptr for chsa %04x\n", chsa); return -1; /* FIFO address error */ } -#endif + if (dibp->chan_fifo_in == ((dibp->chan_fifo_out-1+FIFO_SIZE) % FIFO_SIZE)) { sim_debug(DEBUG_EXP, &cpu_dev, - "FIFO_Put FIFO full for chsa %04x\n", chsa); + "FIFO_Put ERR FIFO full for chsa %04x\n", chsa); return -1; /* FIFO Full */ } dibp->chan_fifo[dibp->chan_fifo_in] = entry; /* add new entry */ @@ -162,16 +159,13 @@ int32 FIFO_Put(uint16 chsa, uint32 entry) /* get the next entry from the FIFO */ int32 FIFO_Get(uint16 chsa, uint32 *old) { -#ifdef OLD_CHAN - DIB *dibp = dib_unit[chsa & 0x7f00]; /* get DIB pointer for channel */ -#else DIB *dibp = dib_chan[get_chan(chsa)]; /* get DIB pointer for channel */ if (dibp == NULL) { sim_debug(DEBUG_EXP, &cpu_dev, - "FIFO_Get NULL dib ptr for chsa %04x\n", chsa); + "FIFO_Get ERR NULL dib ptr for chsa %04x\n", chsa); return -1; /* FIFO address error */ } -#endif + /* see if the FIFO is empty */ if (dibp->chan_fifo_in == dibp->chan_fifo_out) { return -1; /* FIFO is empty, tell caller */ @@ -186,16 +180,12 @@ int32 FIFO_Get(uint16 chsa, uint32 *old) int32 FIFO_Num(uint16 chsa) { int32 num; /* number of entries */ -#ifdef OLD_CHAN - DIB *dibp = dib_unit[chsa & 0x7f00]; /* get DIB pointer for channel */ -#else DIB *dibp = dib_chan[get_chan(chsa)]; /* get DIB pointer for channel */ if (dibp == NULL) { sim_debug(DEBUG_EXP, &cpu_dev, - "FIFO_Num NULL dib ptr for chsa %04x\n", chsa); + "FIFO_Num ERR NULL dib ptr for chsa %04x\n", chsa); return 0; /* FIFO address error */ } -#endif /* calc entries */ num = (dibp->chan_fifo_in - dibp->chan_fifo_out + FIFO_SIZE) % FIFO_SIZE; return (num>1); /* two words/entry */ @@ -295,8 +285,11 @@ uint32 find_int_lev(uint16 chsa) /* get the device entry for channel in SPAD */ uint32 spadent = SPAD[get_chan(chsa)]; /* get spad device entry for logical channel */ - if (spadent == 0 || spadent == 0xffffffff) /* see if valid entry */ + if (spadent == 0 || spadent == 0xffffffff) { /* see if valid entry */ + sim_debug(DEBUG_EXP, &cpu_dev, + "find_int_lev ERR chsa %04x spadent %08x\n", chsa, spadent); return 0; /* not found */ + } inta = ((~spadent)>>16)&0x7f; /* get interrupt level */ sim_debug(DEBUG_IRQ, &cpu_dev, @@ -313,12 +306,18 @@ uint32 find_int_icb(uint16 chsa) uint32 spadent = SPAD[get_chan(chsa)]; /* get spad device entry for logical channel */ inta = find_int_lev(chsa); /* find the int level */ - if (inta == 0) + if (inta == 0) { + sim_debug(DEBUG_EXP, &cpu_dev, + "find_int_icb ERR chsa %04x inta %02x\n", chsa, inta); return 0; /* not found */ + } /* add interrupt vector table base address plus int # byte address offset */ icba = SPAD[0xf1] + (inta<<2); /* interrupt vector address in memory */ - if (!MEM_ADDR_OK(icba)) /* needs to be valid address in memory */ + if (!MEM_ADDR_OK(icba)) { /* needs to be valid address in memory */ + sim_debug(DEBUG_EXP, &cpu_dev, + "find_int_icb ERR chsa %04x icba %02x\n", chsa, icba); return 0; /* not found */ + } icba = RMW(icba); /* get address of ICB from memory */ sim_debug(DEBUG_IRQ, &cpu_dev, "find_int_icb icba %06x SPADC %08x chsa %04x lev %02x SPADI %08x INTS %08x\n", @@ -335,12 +334,17 @@ UNIT *find_unit_ptr(uint16 chsa) dibp = dib_unit[chsa]; /* get DIB pointer from device address */ if (dibp == 0) { /* if zero, not defined on system */ + sim_debug(DEBUG_EXP, &cpu_dev, + "find_unit_ptr ERR chsa %04x dibp %p\n", chsa, dibp); 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 */ + if (uptr == 0) { /* if zero, no devices defined on system */ + sim_debug(DEBUG_EXP, &cpu_dev, + "find_unit_ptr ERR chsa %04x uptr %p\n", chsa, uptr); return NULL; /* tell caller */ + } for (i = 0; i < dibp->numunits; i++) { /* search through units to get a match */ if (chsa == GET_UADDR(uptr->u3)) { /* does ch/sa match? */ @@ -348,6 +352,8 @@ 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 */ } @@ -360,15 +366,23 @@ CHANP *find_chanp_ptr(uint16 chsa) int i; dibp = dib_unit[chsa]; /* get DIB pointer from unit address */ - if (dibp == 0) /* if zero, not defined on system */ + 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); 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); 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 */ + 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); return NULL; /* tell caller */ + } for (i = 0; i < dibp->numunits; i++) { /* search through units to get a match */ if (chsa == GET_UADDR(uptr->u3)) { /* does ch/sa match? */ @@ -377,6 +391,8 @@ 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); return NULL; /* device not found on system */ } @@ -411,8 +427,7 @@ int readbuff(CHANP *chp) sim_debug(DEBUG_EXP, &cpu_dev, "readbuff PCHK addr %08x to big mem %08x status %04x\n", addr, MEMSIZE, chp->chan_status); - chp->chan_byte = BUFF_CHNEND; /* force channel end */ - irq_pend = 1; /* and we have an interrupt */ + chp->chan_byte = BUFF_CHNEND; /* force channel end & busy */ return 1; /* done, with error */ } chp->chan_buf = RMB(addr&MASK24); /* get 1 byte */ @@ -432,8 +447,7 @@ int writebuff(CHANP *chp) sim_debug(DEBUG_EXP, &cpu_dev, "writebuff PCHK addr %08x to big mem %08x status %04x\n", addr, MEMSIZE, chp->chan_status); - chp->chan_byte = BUFF_CHNEND; /* end the I/O */ -//040220irq_pend = 1; + chp->chan_byte = BUFF_CHNEND; /* force channel end & busy */ return 1; } addr &= MASK24; /* good address, write the byte */ @@ -452,7 +466,8 @@ int32 load_ccw(CHANP *chp, int32 tic_ok) uint32 word1 = 0; uint32 word2 = 0; int docmd = 0; - UNIT *uptr = find_unit_ptr(chp->chan_dev); /* find the unit pointer */ +//Z UNIT *uptr = find_unit_ptr(chp->chan_dev); /* find the unit pointer */ + UNIT *uptr = chp->unitptr; /* get the unit ptr */ uint16 chan = get_chan(chp->chan_dev); /* our channel */ uint16 devstat = 0; @@ -492,6 +507,18 @@ loop: "load_ccw @%06x read ccw chan %02x IOCD wd 1 %08x wd 2 %08x\n", chp->chan_caw, chan, word1, word2); +#ifndef FOR_DEBUG + if ((word2>>16) & (FLAG_CC|FLAG_DC)) { + uint32 word3 = 0; + uint32 word4 = 0; + readfull(chp, chp->chan_caw+8, &word3); /* read word3 from memory */ + readfull(chp, chp->chan_caw+12, &word4); /* read word4 from memory */ + sim_debug(DEBUG_XIO, &cpu_dev, + "load_ccw @%06x read ccw chan %02x IOCD wd 3 %08x wd 4 %08x\n", + chp->chan_caw, chan, word3, word4); + } +#endif + /* TIC can't follow TIC or be first in command chain */ if (((word1 >> 24) & 0xf) == CMD_TIC) { if (tic_ok) { @@ -505,7 +532,6 @@ loop: chp->chan_status |= STATUS_PCHK; /* program check for invalid tic */ sim_debug(DEBUG_EXP, &cpu_dev, "load_ccw TIC ERROR chan_status[%04x] %04x\n", chan, chp->chan_status); - irq_pend = 1; /* status pending */ return 1; /* error return */ } @@ -518,12 +544,15 @@ loop: docmd = 1; /* show we have a command */ } + /* added next line 051220 */ + chp->chan_status = 0; /* clear status for next IOCD */ /* Set up for this command */ /* make a 24 bit address */ chp->ccw_addr = word1 & MASK24; /* set the data/seek address */ chp->chan_caw += 8; /* point to to next IOCD */ chp->ccw_count = word2 & 0xffff; /* get 16 bit byte count from IOCD WD 2*/ - chp->chan_byte = BUFF_EMPTY; /* no bytes transferred yet */ +//Z chp->chan_byte = BUFF_EMPTY; /* no bytes transferred yet */ + chp->chan_byte = BUFF_BUSY; /* busy & no bytes transferred yet */ chp->ccw_flags = (word2 >> 16) & 0xffff; /* get flags from bits 0-7 of WD 2 of IOCD */ if (chp->ccw_flags & FLAG_PCI) { /* do we have prog controlled int? */ chp->chan_status |= STATUS_PCI; /* set PCI flag in status */ @@ -531,7 +560,7 @@ loop: } sim_debug(DEBUG_XIO, &cpu_dev, - "load_ccw @%06x read docmd %02x addr %06x count %04x chan %04x ccw_flags %04x\n", + "load_ccw @%06x read docmd %01x addr %06x count %04x chan %04x ccw_flags %04x\n", chp->chan_caw, docmd, chp->ccw_addr, chp->ccw_count, chan, chp->ccw_flags); #ifdef HACK_FOR_LPR @@ -546,8 +575,9 @@ loop: if (docmd) { /* see if we need to process a command */ DIB *dibp = dib_unit[chp->chan_dev]; /* get the DIB pointer */ - - uptr = find_unit_ptr(chp->chan_dev); /* find the unit pointer */ + +//Z uptr = find_unit_ptr(chp->chan_dev); /* find the unit pointer */ + uptr = chp->unitptr; /* get the unit ptr */ if (dibp == 0 || uptr == 0) { chp->chan_status |= STATUS_PCHK; /* program check if it is */ return 1; /* if none, error */ @@ -563,6 +593,8 @@ loop: // if (devstat & 0xff00) { /* any chan errors returned */ // chp->chan_status = (chp->chan_status & 0xff00) | (devstat & 0xff); // } +//051220chp->chan_status = (chp->chan_status & 0xff00) | devstat; +// chp->chan_status = devstat; chp->chan_status = (chp->chan_status & 0xff00) | devstat; sim_debug(DEBUG_XIO, &cpu_dev, @@ -590,7 +622,7 @@ loop: return 1; /* error return */ #endif } -#ifdef XXX042320_042720_ADD_BACK +#ifndef XXX042320_042720_ADD_BACK_ADD_BACK_051220 /* NOTE this code needed for MPX 1.X to run! */ /* see if command completed */ /* we have good status */ @@ -612,6 +644,7 @@ loop: } #endif } + /* the device processor return OK (0), so wait for I/O to complete */ /* nothing happening, so return */ sim_debug(DEBUG_XIO, &cpu_dev, "load_ccw @%06x return, chan %04x status %04x count %04x irq_pend %1x\n", @@ -631,13 +664,13 @@ int chan_read_byte(uint16 chsa, uint8 *data) if (chp->chan_status & STATUS_ERROR) /* check channel error status */ return 1; /* return error */ - if (chp->chan_byte == BUFF_CHNEND) - return 1; /* return error */ + if (chp->chan_byte == BUFF_CHNEND) /* check for end of data */ + return 1; /* yes, return error */ if (chp->ccw_count == 0) { /* see if more data required */ if ((chp->ccw_flags & FLAG_DC) == 0) { /* see if Data Chain */ //040120 chp->chan_status |= STATUS_CEND; /* no, end of data */ -/*BACK*/ chp->chan_status |= STATUS_CEND; /* no, end of data */ +//051520/*BACK*/ chp->chan_status |= STATUS_CEND; /* no, end of data */ chp->chan_byte = BUFF_CHNEND; /* buffer end too */ sim_debug(DEBUG_XIO, &cpu_dev, "chan_read_byte no DC chan end, cnt %04x addr %06x chan %04x\n", @@ -675,7 +708,7 @@ int test_write_byte_end(uint16 chsa) CHANP *chp = find_chanp_ptr(chsa); /* get channel prog pointer */ /* see if at end of buffer */ - if (chp->chan_byte == BUFF_CHNEND) + if (chp->chan_byte == BUFF_CHNEND) /* check for end of data */ return 1; /* return done */ if (chp->ccw_count == 0) { if ((chp->ccw_flags & FLAG_DC) == 0) { /* see if we have data chaining */ @@ -700,7 +733,7 @@ int chan_write_byte(uint16 chsa, uint8 *data) return 1; /* return error */ /* see if at end of buffer */ - if (chp->chan_byte == BUFF_CHNEND) { + if (chp->chan_byte == BUFF_CHNEND) { /* check for end of data */ sim_debug(DEBUG_EXP, &cpu_dev, "chan_write_byte BUFF_CHNEND ccw_flags %04x addr %06x cnt %04x\n", chp->ccw_flags, chp->ccw_addr, chp->ccw_count); @@ -739,40 +772,37 @@ int chan_write_byte(uint16 chsa, uint8 *data) } } /* we have data byte to write to chp->ccw_addr */ - if (chsa == 0x7efc) - sim_debug(DEBUG_EXP, &cpu_dev, "chan_write_byte non zero ccw_count[%04x]=%04x\n", - chsa, chp->ccw_count); - else - sim_debug(DEBUG_DATA, &cpu_dev, "chan_write_byte non zero ccw_count[%04x]=%04x\n", - chsa, chp->ccw_count); - /* see if we want to skip writing data to memory */ if (chp->ccw_flags & FLAG_SKIP) { chp->ccw_count--; /* decrement skip count */ - chp->chan_byte = BUFF_EMPTY; /* no data */ +//Z chp->chan_byte = BUFF_EMPTY; /* no data */ + chp->chan_byte = BUFF_BUSY; /* busy, but no data */ if ((chp->ccw_cmd & 0xff) == CMD_RDBWD) chp->ccw_addr--; /* backward */ else chp->ccw_addr++; /* forward */ - sim_debug(DEBUG_XIO, &cpu_dev, "chan_write_byte SKIP ret addr %08x cnt %04x\n", + sim_debug(DEBUG_DETAIL, &cpu_dev, "chan_write_byte SKIP ret addr %08x cnt %04x\n", chp->ccw_addr, chp->ccw_count); return 0; } - if (chsa == 0x7efc) - sim_debug(DEBUG_EXP, &cpu_dev, "chan_write_byte of data %02x to %06x\n", - *data, chp->ccw_addr); - else - sim_debug(DEBUG_DETAIL, &cpu_dev, "chan_write_byte of data %02x to %06x\n", - *data, chp->ccw_addr); chp->chan_buf = *data; /* get data byte */ if (writebuff(chp)) /* write the byte */ return 1; - chp->ccw_count--; - chp->chan_byte = BUFF_EMPTY; /* no data to go out */ +#ifndef FOR_DEBUG + if (chsa == 0x7efc) { + sim_debug(DEBUG_EXP, &cpu_dev, + "chan_write_byte write %02x to mem addr %06x cnt %04x\n", + chp->chan_buf, chp->ccw_addr, chp->ccw_count); + } +#endif + + chp->ccw_count--; /* reduce count */ +//Z chp->chan_byte = BUFF_EMPTY; /* no data to go out */ + chp->chan_byte = BUFF_BUSY; /* busy, but no data */ if ((chp->ccw_cmd & 0xff) == CMD_RDBWD) /* see if reading backwards */ - chp->ccw_addr -= 1; /* no, use next address */ + chp->ccw_addr -= 1; /* no, use previous address */ else - chp->ccw_addr += 1; /* yes, use previous address */ + chp->ccw_addr += 1; /* yes, use next address */ return 0; } @@ -813,15 +843,8 @@ void chan_end(uint16 chsa, uint16 flags) { "chan_end entry chsa %04x flags %04x status %04x cmd %02x\n", chsa, flags, chp->chan_status, chp->ccw_cmd); -// if (chp->chan_byte & BUFF_DIRTY) { - if (chp->chan_byte == BUFF_DIRTY) { - sim_debug(DEBUG_XIO, &cpu_dev, - "chan_end writing DIRTY chsa %04x flags %04x status %04x cmd %02x\n", - chsa, flags, chp->chan_status, chp->ccw_cmd); - if (writebuff(chp)) /* write remaining data */ - return; /* error */ - } - chp->chan_byte = BUFF_EMPTY; /* we are empty now */ +//Z chp->chan_byte = BUFF_EMPTY; /* we are empty & still busy now */ + chp->chan_byte = BUFF_BUSY; /* we are empty & still busy now */ chp->chan_status |= STATUS_CEND; /* set channel end */ chp->chan_status |= ((uint16)flags); /* add in the callers flags */ @@ -847,7 +870,8 @@ 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); - chp->ccw_cmd = 0; /* reset the completed channel command */ +//DEL 051320 chp->ccw_cmd = 0; /* reset the completed channel command */ +///*051520*/ chp->ccw_cmd = 0; /* reset the completed channel command */ /* Diags do not want SLI if we have no device end status */ #ifndef OLDWAY_040120 @@ -869,7 +893,8 @@ void chan_end(uint16 chsa, uint16 flags) { /* test for device or controller end */ if (chp->chan_status & (STATUS_DEND|STATUS_CEND)) { - chp->chan_byte = BUFF_EMPTY; /* clear byte flag */ +//Z chp->chan_byte = BUFF_EMPTY; /* clear byte flag */ + chp->chan_byte = BUFF_BUSY; /* we are empty & still busy now */ while ((chp->ccw_flags & FLAG_DC)) { /* handle data chaining */ if (load_ccw(chp, 1)) /* continue channel program */ break; /* error */ @@ -879,7 +904,8 @@ void chan_end(uint16 chsa, uint16 flags) { } } //040120chp->chan_byte = BUFF_DONE; /* clear byte flag */ - chp->chan_byte = BUFF_EMPTY; /* clear byte flag */ +//Z chp->chan_byte = BUFF_EMPTY; /* clear byte flag */ + chp->chan_byte = BUFF_BUSY; /* we are empty & still busy now */ sim_debug(DEBUG_XIO, &cpu_dev, "chan_end FIFO #%1x IOCL done chsa %04x ccw_flags %04x status %04x\n", FIFO_Num(chsa), chsa, chp->ccw_flags, chp->chan_status); @@ -898,7 +924,6 @@ void chan_end(uint16 chsa, uint16 flags) { sim_debug(DEBUG_XIO, &cpu_dev, "chan_end dev end & CC chsa %04x status %04x IOCLA %08x\n", chsa, chp->chan_status, chp->chan_caw); -// (void)load_ccw(chp, 1); /* go load the next IOCB */ /* Queue us to continue from cpu level */ chp->chan_byte = BUFF_NEXT; /* have main pick us up */ RDYQ_Put(chsa); /* queue us up */ @@ -908,15 +933,15 @@ void chan_end(uint16 chsa, uint16 flags) { /* we have channel end and no CC flag, end command */ chsa = chp->chan_dev; /* get the chan/sa */ sim_debug(DEBUG_XIO, &cpu_dev, - "chan_end chan end & no CC chsa %04x status %04x\n", - chsa, chp->chan_status); + "chan_end chan end & no CC chsa %04x status %04x cmd %02x\n", + chsa, chp->chan_status, chp->ccw_cmd); /* we have completed channel program */ /* handle case where we are loading the O/S on boot */ /* if loading, store status to be discovered by scan_chan */ if (!loading) { sim_debug(DEBUG_XIO, &cpu_dev, - "chan_end call store_csw dev/chan end chsa %04x cpustatus %08x iocla %08x\n", + "chan_end call store_csw dev/chan end chsa %04x cpustat %08x iocla %08x\n", chsa, CPUSTATUS, chp->chan_caw); } else { /* we are loading, so keep moving */ @@ -924,9 +949,13 @@ void chan_end(uint16 chsa, uint16 flags) { "chan_end we are loading O/S with DE & CE, keep status chsa %04x status %08x\n", chsa, chp->chan_status); } - /* store the status in device fifo to continue from cpu level */ - chp->chan_byte = BUFF_DONE; /* have main pick us up */ + /* store the status in channel FIFO to continue from cpu level */ + chp->chan_byte = BUFF_DONE; /* we are done */ + /* store_csw will change chan_byte to BUFF_DONE */ store_csw(chp); /* store the status */ + sim_debug(DEBUG_XIO, &cpu_dev, + "chan_end after store_csw call chsa %04x status %08x chan_byte %02x\n", + chsa, chp->chan_status, chp->chan_byte); } } /* following statement required for boot to work */ @@ -956,7 +985,7 @@ int16 post_csw(CHANP *chp, uint32 rstat) /* remove user specified bits */ sw2 &= ~rstat; /* remove bits */ /* we have status to post, do it now */ - chp->chan_byte = BUFF_NEWCMD; /* show done */ + chp->chan_byte = BUFF_DONE; /* show done & not busy */ /* save the status double word to memory */ WMW(incha, sw1); /* save sa & IOCD address in status WD 1 loc */ WMW(incha+4, sw2); /* save status and residual cnt in status WD 2 loc */ @@ -986,11 +1015,15 @@ void store_csw(CHANP *chp) sim_debug(DEBUG_EXP, &cpu_dev, "store_csw FIFO Overflow ERROR on chsa %04x\n", chsa); } - sim_debug(DEBUG_IRQ, &cpu_dev, - "store_csw FIFO #%1x write chsa %04x sw1 %08x sw2 %08x incha %08x\n", - FIFO_Num(chsa), chsa, stwd1, stwd2, chp->chan_inch_addr); + sim_debug(DEBUG_XIO, &cpu_dev, + "store_csw FIFO #%1x write chsa %04x sw1 %08x sw2 %08x incha %08x cmd %02x\n", + FIFO_Num(chsa), chsa, stwd1, stwd2, chp->chan_inch_addr, chp->ccw_cmd); chp->chan_status = 0; /* no status anymore */ - chp->chan_byte = BUFF_CHNEND; /* show done */ + chp->ccw_cmd = 0; /* no command anymore */ + /* we are done with SIO, but status still needs to be posted */ + /* UTX does not like waiting, so show we are done */ +//Z chp->chan_byte = BUFF_CHNEND; /* show done with data */ + chp->chan_byte = BUFF_DONE; /* show done with data */ irq_pend = 1; /* wakeup controller */ } @@ -1021,38 +1054,49 @@ t_stat checkxio(uint16 chsa, uint32 *status) { DIB *dibp; /* device information pointer */ UNIT *uptr; /* pointer to unit in channel */ uint32 chan_icb; /* Interrupt level context block address */ - uint32 iocla; /* I/O channel IOCL address int ICB */ +//Z uint32 iocla; /* I/O channel IOCL address int ICB */ CHANP *chp; /* channel program pointer */ uint16 chan = get_chan(chsa); /* get the logical channel number */ - uint32 inta, incha; + uint32 inta; +//Z uint32 incha; DEVICE *dptr; /* DEVICE pointer */ sim_debug(DEBUG_XIO, &cpu_dev, "checkxio entry chsa %04x\n", chsa); - dibp = dib_unit[chsa]; /* get the DIB pointer */ - chp = find_chanp_ptr(chsa); /* find the chanp pointer */ - uptr = find_unit_ptr(chsa); /* find pointer to unit on channel */ - dptr = get_dev(uptr); /* pointer to DEVICE structure */ - if (dibp == 0 || uptr == 0 || chp == 0) { /* if no dib or unit ptr, CC3 on return */ + dibp = dib_chan[chan]; /* get DIB pointer for channel */ + if (dibp == 0) goto nothere; + +//Z chp = find_chanp_ptr(chsa&0x7f00); /* find the chanp pointer */ + chp = find_chanp_ptr(chsa); /* find the chanp pointer */ + if (chp == 0) goto nothere; + +//Z uptr = find_unit_ptr(chsa&0x7f00); /* find pointer to unit on channel */ + uptr = find_unit_ptr(chsa); /* find pointer to unit on channel */ +//Z uptr = chp->unitptr; /* get the unit ptr */ + + if (uptr == 0) { /* if no dib or unit ptr, CC3 on return */ +nothere: *status = CC3BIT; /* not found, so CC3 */ sim_debug(DEBUG_EXP, &cpu_dev, "checkxio chsa %04x is not found, CC3 return\n", chsa); return SCPE_OK; /* not found, CC3 */ } - if ((uptr->flags & UNIT_ATTABLE) && ((uptr->flags & UNIT_ATT) == 0)) { /* is unit attached? */ + /* 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 chsa %04x is not attached, CC3 return\n", chsa); *status = CC3BIT; /* not attached, so error CC3 */ return SCPE_OK; /* not found, CC3 */ } - inta = find_int_lev(chsa); /* Interrupt Level for channel */ - chan_icb = find_int_icb(chsa); /* Interrupt level context block address */ + inta = find_int_lev(chsa&0x7f00); /* Interrupt Level for channel */ + chan_icb = find_int_icb(chsa&0x7f00); /* Interrupt level context block address */ sim_debug(DEBUG_XIO, &cpu_dev, - "checkxio int spad %08x icb %06x inta %02x chan %04x\n", - SPAD[inta+0x80], chan_icb, inta, chan); + "checkxio int spad %08x icb %06x inta %02x chan %04x chan_byte %02x\n", + SPAD[inta+0x80], chan_icb, inta, chan, chp->chan_byte); +#ifdef FOR_DEBUG_ONLY /* get the address of the interrupt IVL in main memory */ iocla = RMW(chan_icb+16); /* iocla is in wd 4 of ICB */ incha = RMW(chan_icb+20); /* status is in wd 5 of ICB chp->chan_inch_addr */ @@ -1064,21 +1108,27 @@ t_stat checkxio(uint16 chsa, uint32 *status) { sim_debug(DEBUG_XIO, &cpu_dev, "checkxio busy ck2 chsa %04x ICBincha %08x SW1 %08x SW2 %08x\n", chsa, incha, RMW(incha), RMW(incha+4)); +#endif /* check for a Command or data chain operation in progresss */ - if (chp->ccw_cmd != 0 || (chp->ccw_flags & (FLAG_DC|FLAG_CC)) != 0) { +//Z if (chp->ccw_cmd != 0 || (chp->ccw_flags & (FLAG_DC|FLAG_CC)) != 0) { + if (chp->chan_byte & BUFF_BUSY) { sim_debug(DEBUG_EXP, &cpu_dev, - "checkxio busy return CC3&CC4 chsa %04x chan %04x cmd %02x flags %04x\n", - chsa, chan, chp->ccw_cmd, chp->ccw_flags); + "checkxio busy return CC3&CC4 chsa %04x chan %04x cmd %02x flags %04x byte %02x\n", + chsa, chan, chp->ccw_cmd, chp->ccw_flags, chp->chan_byte); *status = CC4BIT|CC3BIT; /* busy, so CC3&CC4 */ return SCPE_OK; /* just busy CC3&CC4 */ } + + 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 */ +//BADUTX*status = CC1BIT; /* CCs = 1, not busy */ else /* return CC1 for non iop/mfp devices */ *status = CC1BIT; /* CCs = 1, not busy */ +// *status = 0; /* CCs = 0, OK return */ sim_debug(DEBUG_XIO, &cpu_dev, "checkxio done CC status %08x\n", *status); return SCPE_OK; /* No CC's all OK */ } @@ -1098,11 +1148,11 @@ t_stat startxio(uint16 chsa, uint32 *status) { CHANP *chp; /* channel program pointer */ uint16 chan = get_chan(chsa); /* get the channel number */ uint32 tempa, inta, incha; - -#ifndef OLD_CHAN uint32 word1, word2, cmd; sim_debug(DEBUG_XIO, &cpu_dev, "startxio entry chsa %04x\n", chsa); + /* We have to validate all the addresses and parameters for the SIO */ + /* before calling load_ccw which does it again for each IOCL step */ inta = find_int_lev(chsa); /* Interrupt Level for channel */ chan_icb = find_int_icb(chsa); /* Interrupt level context block address */ sim_debug(DEBUG_XIO, &cpu_dev, @@ -1114,6 +1164,7 @@ t_stat startxio(uint16 chsa, uint32 *status) { 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 */ if (cmd == 0) { /* INCH command? */ tempa = word2 & MASK16; /* get count */ if ((word2 & MASK16) == 36) /* see if disk with 224 wd buffer */ @@ -1128,12 +1179,11 @@ t_stat startxio(uint16 chsa, uint32 *status) { sim_debug(DEBUG_XIO, &cpu_dev, "startxio do normal chsa %04x iocla %06x IOCD1 %08x IOCD2 %08x\n", chsa, iocla, RMW(iocla), RMW(iocla+4)); -#endif - sim_debug(DEBUG_XIO, &cpu_dev, "startxio entry chsa %04x\n", chsa); dibp = dib_unit[chsa]; /* get the DIB pointer */ chp = find_chanp_ptr(chsa); /* find the chanp pointer */ - uptr = find_unit_ptr(chsa); /* find pointer to unit on channel */ +//Z uptr = find_unit_ptr(chsa); /* find pointer to unit on channel */ + uptr = chp->unitptr; /* get the unit ptr */ if (dibp == 0 || uptr == 0 || chp == 0) { /* if no dib, unit or channel ptr, CC3 return */ *status = CC3BIT; /* not found, so CC3 */ @@ -1150,18 +1200,20 @@ t_stat startxio(uint16 chsa, uint32 *status) { } inta = find_int_lev(chsa); /* Interrupt Level for channel */ -#ifdef NONO +#ifndef NONO if ((INTS[inta]&INTS_ACT) || (SPAD[inta+0x80]&SINT_ACT)) { /* look for level active */ + /* just output a warning */ sim_debug(DEBUG_XIO, &cpu_dev, - "SIO Busy INTS ACT FIFO #%1x irq %02x SPAD %08x INTS %08x\n", - FIFO_Num(SPAD[inta+0x80] & 0x7f00), inta, SPAD[inta+0x80], INTS[inta]); - *status = CC4BIT|CC3BIT; /* busy, so CC3&CC4 */ - return SCPE_OK; /* just busy CC3&CC4 */ + "SIO Busy INTS ACT FIFO #%1x irq %02x SPAD %08x INTS %08x chan_byte %02x\n", + FIFO_Num(SPAD[inta+0x80] & 0x7f00), inta, SPAD[inta+0x80], INTS[inta], chp->chan_byte); +// *status = CC4BIT|CC3BIT; /* busy, so CC3&CC4 */ +// return SCPE_OK; /* just busy CC3&CC4 */ } #endif /* check for a Command or data chain operation in progresss */ - if (chp->ccw_cmd != 0 || (chp->ccw_flags & (FLAG_DC|FLAG_CC)) != 0) { +//Z if (chp->ccw_cmd != 0 || (chp->ccw_flags & (FLAG_DC|FLAG_CC)) != 0) { + if (chp->chan_byte & BUFF_BUSY) { sim_debug(DEBUG_XIO, &cpu_dev, "startxio busy return CC3&CC4 chsa %04x chan %04x\n", chsa, chan); *status = CC4BIT|CC3BIT; /* busy, so CC3&CC4 */ @@ -1185,7 +1237,7 @@ t_stat startxio(uint16 chsa, uint32 *status) { chsa, iocla, RMW(iocla), RMW(iocla+4)); sim_debug(DEBUG_CMD, &cpu_dev, "$$$ SIO %04x %04x cmd %02x ccw_flags %04x\n", - chsa, chan, chp->ccw_cmd, chp->ccw_flags); + chsa, chan, chp->ccw_cmd, chp->ccw_flags); /* determine if channel DIB has a pre startio command processor */ if (dibp->pre_io != NULL) { /* NULL if no startio function */ @@ -1207,74 +1259,34 @@ t_stat startxio(uint16 chsa, uint32 *status) { chp->chan_int = inta; /* save interrupt level in channel */ chp->chan_status = 0; /* no channel status yet */ chp->chan_caw = iocla; /* get iocla address in memory */ - chp->chan_byte = BUFF_NEWCMD; /* starting a new program */ - /* set status words in memory to first IOCD information */ + /* set status words in memory to first IOCD information */ sim_debug(DEBUG_XIO, &cpu_dev, "$$ SIO start IOCL processing chsa %04x iocla %08x incha %08x\n", chsa, iocla, incha); -#ifndef QUEUE_IO - /* try queueing the SIO */ - /* Queue us to continue from cpu level */ + /* We are queueing the SIO */ + /* Queue us to continue IOCL from cpu level & make busy */ chp->chan_byte = BUFF_NEXT; /* have main pick us up */ RDYQ_Put(chsa); /* queue us up */ sim_debug(DEBUG_XIO, &cpu_dev, "$$$ SIO queued chsa %04x iocla %06x IOCD1 %08x IOCD2 %08x\n", chsa, iocla, RMW(iocla), RMW(iocla+4)); -#endif - -#ifdef QUEUE_IO - /* start processing the IOCL */ - if (load_ccw(chp, 0) || (chp->chan_status & STATUS_PCI)) { - /* we have an error or user requested interrupt, return status */ - sim_debug(DEBUG_EXP, &cpu_dev, "startxio FIFO #%1x store_csw CC2 chan %04x status %08x\n", - FIFO_Num(chsa), chan, chp->chan_status); -#ifdef DISABLE_041320 - /* DIAG's want CC1 with memory access error */ - if (chp->chan_status & STATUS_PCHK) { - chp->chan_status &= ~STATUS_LENGTH; /* clear incorrect length */ - chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* show I/O complete & store status in FIFO */ - sim_debug(DEBUG_EXP, &cpu_dev, - "startxio Error1 FIFO #%1x store_csw CC1 chan %04x status %08x\n", - FIFO_Num(chsa), chan, chp->chan_status); - *status = CC1BIT; /* CCs = 1, SIO accepted & queued, no echo status */ -// irq_pend = 1; /* still pending int */ - return SCPE_OK; /* CC2 (0x20) status stored */ - } -#endif - /* TODO maybe need to do chan_end first */ - chp->chan_status &= ~STATUS_PCI; /* remove PCI status bit */ -// chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* show I/O complete & store status in FIFO */ - chan_end(chsa, SNS_CHNEND); /* show I/O complete & store status in FIFO */ -// store_csw(chp); /* store the status in the inch status dw */ - /* try 041920 for dexp */ - if (FIFO_Num(chsa)) { /* post the status */ - post_csw(chp, 0); - *status = CC2BIT; /* status stored, so CC2 */ - sim_debug(DEBUG_EXP, &cpu_dev, - "startxio Error2 FIFO #%1x store_csw CC2 chan %04x status %08x\n", - FIFO_Num(chsa), chan, chp->chan_status); - irq_pend = 1; /* still pending int */ - return SCPE_OK; /* CC2 (0x20) status stored */ - } - } -#endif *status = CC1BIT; /* CCs = 1, SIO accepted & queued, no echo status */ -// *status = 0; /*TRY*/ /* 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", chsa, chp->chan_status, iocla, *status); return SCPE_OK; /* No CC's all OK */ } /* TIO - I/O status */ -t_stat testxio(uint16 chsa, uint32 *status) { /* test XIO */ +t_stat testxio(uint16 chsa, uint32 *status) { /* test XIO */ DIB *dibp; /* device information pointer */ UNIT *uptr; /* pointer to unit in channel */ uint32 chan_icb; /* Interrupt level context block address */ uint32 iocla; /* I/O channel IOCL address int ICB */ CHANP *chp; /* Channel prog pointers */ +//Z CHANP *pchp; /* parent Channel prog pointers */ uint16 chan = get_chan(chsa); /* get the channel number */ uint32 inta, incha; @@ -1282,7 +1294,9 @@ t_stat testxio(uint16 chsa, uint32 *status) { /* test XIO */ /* get the device entry for the channel in SPAD */ dibp = dib_unit[chsa]; /* get the DIB pointer */ chp = find_chanp_ptr(chsa); /* find the device chanp pointer */ - uptr = find_unit_ptr(chsa); /* find pointer to unit on channel */ +//Z pchp = find_chanp_ptr(chsa&0x7f00); /* find the parent device chanp pointer */ +//Z uptr = find_unit_ptr(chsa); /* find pointer to unit on channel */ + uptr = chp->unitptr; /* get the unit ptr */ if (dibp == 0 || uptr == 0 || chp == 0) { /* if no dib, unit or channel ptr, CC3 return */ *status = CC3BIT; /* not found, so CC3 */ @@ -1299,7 +1313,8 @@ t_stat testxio(uint16 chsa, uint32 *status) { /* test XIO */ } /* check for a Command or data chain operation in progresss */ - if (chp->ccw_cmd != 0 || (chp->ccw_flags & (FLAG_DC|FLAG_CC)) != 0) { +//Z if (chp->ccw_cmd != 0 || (chp->ccw_flags & (FLAG_DC|FLAG_CC)) != 0) { + if (chp->chan_byte & BUFF_BUSY) { sim_debug(DEBUG_XIO, &cpu_dev, "testxio busy return CC4 chsa %04x chan %04x\n", chsa, chan); *status = CC4BIT|CC3BIT; /* busy, so CC3&CC4 */ @@ -1326,6 +1341,7 @@ t_stat testxio(uint16 chsa, uint32 *status) { /* test XIO */ /* the channel is not busy, see if any status to post */ if (post_csw(chp, 0)) { +//BAD STATUS UTX if (post_csw(pchp, 0)) { *status = CC2BIT; /* status stored from SIO, so CC2 */ sim_debug(DEBUG_XIO, &cpu_dev, "testxio END status stored incha %06x chsa %04x sw1 %08x sw2 %08x\n", @@ -1368,7 +1384,8 @@ t_stat stopxio(uint16 chsa, uint32 *status) { /* stop XIO */ /* get the device entry for the logical channel in SPAD */ dibp = dib_unit[chsa]; /* get the DIB pointer */ chp = find_chanp_ptr(chsa); /* find the device chanp pointer */ - uptr = find_unit_ptr(chsa); /* find pointer to unit on channel */ +//Z uptr = find_unit_ptr(chsa); /* find pointer to unit on channel */ + uptr = chp->unitptr; /* get the unit ptr */ if (dibp == 0 || uptr == 0 || chp == 0) { /* if no dib, unit or channel ptr, CC3 return */ *status = CC3BIT; /* not found, so CC3 */ @@ -1394,7 +1411,8 @@ t_stat stopxio(uint16 chsa, uint32 *status) { /* stop XIO */ chsa, chp->ccw_cmd, chp->ccw_flags); /* check for a Command or data chain operation in progresss */ - if (chp->ccw_cmd != 0 || (chp->ccw_flags & (FLAG_DC|FLAG_CC)) != 0) { +//Z if (chp->ccw_cmd != 0 || (chp->ccw_flags & (FLAG_DC|FLAG_CC)) != 0) { + if (chp->chan_byte & BUFF_BUSY) { sim_debug(DEBUG_CMD, &cpu_dev, "stopxio busy return CC1 chsa %04x chan %04x\n", chsa, chan); /* reset the DC or CC bits to force completion after current IOCD */ chp->ccw_flags &= ~(FLAG_DC|FLAG_CC); /* reset chaining bits */ @@ -1420,9 +1438,11 @@ t_stat rschnlxio(uint16 chsa, uint32 *status) { /* reset channel XIO */ sim_debug(DEBUG_XIO, &cpu_dev, "rschnlxio entry chan %04x\n", chan); /* get the device entry for the logical channel in SPAD */ - dibp = dib_unit[chan]; /* get the DIB pointer */ - chp = find_chanp_ptr(chsa); /* find the device chanp pointer */ - uptr = find_unit_ptr(chsa); /* find pointer to unit on channel */ +//Z dibp = dib_unit[chan]; /* get the DIB pointer */ + dibp = dib_chan[get_chan(chan)]; /* get the channel device information pointer */ + chp = find_chanp_ptr(chan); /* find the channel chanp pointer */ +//Z uptr = find_unit_ptr(chsa); /* find pointer to unit on channel */ + uptr = chp->unitptr; /* get the unit ptr */ if (dibp == 0 || uptr == 0 || chp == 0) { /* if no dib, unit or channel ptr, CC3 return */ *status = CC3BIT; /* not found, so CC3 */ @@ -1456,7 +1476,7 @@ t_stat rschnlxio(uint16 chsa, uint32 *status) { /* reset channel XIO */ if (chp == 0) continue; /* not used */ chp->chan_status = 0; /* clear the channel status */ - chp->chan_byte = BUFF_NEWCMD; /* no data yet */ + chp->chan_byte = BUFF_EMPTY; /* no data yet */ chp->ccw_addr = 0; /* clear buffer address */ chp->chan_caw = 0x0; /* clear IOCD address */ chp->ccw_count = 0; /* channel byte count 0 bytes*/ @@ -1487,9 +1507,10 @@ t_stat haltxio(uint16 lchsa, uint32 *status) { /* halt XIO */ spadent = SPAD[chan]; /* get spad device entry for logical channel */ chan = (spadent & 0x7f00) >> 8; /* get real channel */ chsa = (chan << 8) | (lchsa & 0xff); /* merge sa to real channel */ - dibp = dib_unit[chsa]; /* get the DIB pointer */ + dibp = dib_unit[chsa]; /* get the device DIB pointer */ chp = find_chanp_ptr(chsa); /* find the chanp pointer */ - uptr = find_unit_ptr(chsa); /* find pointer to unit on channel */ +//Z uptr = find_unit_ptr(chsa); /* find pointer to unit on channel */ + uptr = chp->unitptr; /* get the unit ptr */ // pchp = find_chanp_ptr(chsa & 0x7f00); /* find the parent channel pointer */ sim_debug(DEBUG_XIO, &cpu_dev, "haltxio 1 chsa %04x chan %04x\n", chsa, chan); @@ -1522,21 +1543,23 @@ t_stat haltxio(uint16 lchsa, uint32 *status) { /* halt XIO */ sim_debug(DEBUG_XIO, &cpu_dev, "$$$ HIO chsa %04x chan %04x cmd %02x ccw_flags %04x\n", chsa, chan, chp->ccw_cmd, chp->ccw_flags); - if (chp->ccw_cmd == 0 && (chp->ccw_flags & (FLAG_DC|FLAG_CC)) == 0) { +//ZZif (chp->ccw_cmd == 0 && (chp->ccw_flags & (FLAG_DC|FLAG_CC)) == 0) { + if ((chp->chan_byte & BUFF_BUSY) == 0) { /* the channel is not busy, so return OK */ /* diag wants an interrupt for a non busy HIO ??? */ sim_debug(DEBUG_XIO, &cpu_dev, "$$$ HIO DIAG chsa %04x chan %04x cmd %02x ccw_flags %04x status %04x\n", chsa, chan, chp->ccw_cmd, chp->ccw_flags, *status); - chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* show I/O complete */ +//ZZ chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* show I/O complete */ irq_pend = 1; /* still pending int */ *status = CC1BIT; /* request accepted, no status, so CC1 */ - goto hioret; /* CC2 and OK */ +//ZZ goto hioret; /* CC1 and OK */ + goto hiogret; /* CC1 and OK */ } /* the channel is busy, so process */ - chp->chan_byte = BUFF_CHNEND; /* thats all the data we want */ +//ZZchp->chan_byte = BUFF_CHNEND; /* thats all the data we want */ /* see if we have a haltio device entry */ if (dibp->halt_io != NULL) { /* NULL if no haltio function */ @@ -1553,7 +1576,10 @@ t_stat haltxio(uint16 lchsa, uint32 *status) { /* halt XIO */ /* chan_end called in hio device service routine */ /* the device is no longer busy, post status */ - if (post_csw(chp, ((STATUS_LENGTH|STATUS_PCI|STATUS_EXPT|STATUS_CHECK) << 16))) { + /* remove SLI, PCI and Unit check status bits */ +/// if (post_csw(chp, ((STATUS_LENGTH|STATUS_PCI|STATUS_EXPT|STATUS_CHECK) << 16))) { + if (post_csw(chp, ((STATUS_LENGTH|STATUS_PCI|STATUS_EXPT) << 16))) { +/// UTX if (post_csw(chp, ((STATUS_LENGTH|STATUS_PCI|STATUS_CHECK) << 16))) { /* TODO clear SLI bit in status */ // chp->chan_status &= ~STATUS_LENGTH; /* remove SLI status bit */ // chp->chan_status &= ~STATUS_PCI; /* remove PCI status bit */ @@ -1561,7 +1587,10 @@ t_stat haltxio(uint16 lchsa, uint32 *status) { /* halt XIO */ *status = CC2BIT; /* status stored */ goto hioret; /* CC2 and OK */ } - } else { + } + /* the device is not busy, so cmd has not started */ +#ifdef DROP_THRU + else { /* we have completed the I/O without error */ /* the channel is not busy, so return OK */ sim_debug(DEBUG_XIO, &cpu_dev, @@ -1570,10 +1599,12 @@ t_stat haltxio(uint16 lchsa, uint32 *status) { /* halt XIO */ *status = CC1BIT; /* request accepted, no status, so CC1 */ goto hioret; /* just return */ } +#endif } /* device does not have a HIO entry, so terminate the I/O */ /* check for a Command or data chain operation in progresss */ - if (chp->ccw_cmd != 0 || (chp->ccw_flags & (FLAG_DC|FLAG_CC)) != 0) { +//Z if (chp->ccw_cmd != 0 || (chp->ccw_flags & (FLAG_DC|FLAG_CC)) != 0) { + if (chp->chan_byte & BUFF_BUSY) { sim_debug(DEBUG_XIO, &cpu_dev, "haltxio busy return CC4 chsa %04x chan %04x\n", chsa, chan); /* reset the DC or CC bits to force completion after current IOCD */ @@ -1581,11 +1612,15 @@ t_stat haltxio(uint16 lchsa, uint32 *status) { /* halt XIO */ chp->chan_status &= ~STATUS_LENGTH; /* remove SLI status bit */ chp->chan_status &= ~STATUS_PCI; /* remove PCI status bit */ chp->ccw_flags &= ~(FLAG_DC|FLAG_CC); /* reset chaining bits */ - chp->chan_byte = BUFF_EMPTY; /* done */ +//Z chp->chan_byte = BUFF_EMPTY; /* done */ + chp->chan_byte = BUFF_BUSY; /* wait for post_csw to be done */ chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITEXP); /* show I/O complete */ /* post the channel status */ - if (post_csw(chp, ((STATUS_LENGTH|STATUS_PCI|STATUS_EXPT|STATUS_CHECK) << 16))) { + /* remove SLI, PCI and Unit check status bits */ +//Z if (post_csw(chp, ((STATUS_LENGTH|STATUS_PCI|STATUS_EXPT|STATUS_CHECK) << 16))) { + if (post_csw(chp, ((STATUS_LENGTH|STATUS_PCI|STATUS_EXPT) << 16))) { +//ZZ if (post_csw(chp, ((STATUS_LENGTH|STATUS_PCI|STATUS_CHECK) << 16))) { /* TODO clear SLI bit in status */ // chp->chan_status &= ~STATUS_LENGTH; /* remove SLI status bit */ // chp->chan_status &= ~STATUS_PCI; /* remove PCI status bit */ @@ -1594,6 +1629,8 @@ t_stat haltxio(uint16 lchsa, uint32 *status) { /* halt XIO */ goto hioret; /* just return */ } } +hiogret: + chp->chan_byte = BUFF_DONE; /* chan prog done */ /* the channel is not busy, so return OK */ *status = CC1BIT; /* request accepted, no status, so CC1 */ hioret: @@ -1643,7 +1680,8 @@ t_stat rsctlxio(uint16 lchsa, uint32 *status) { /* reset controller XIO */ chsa = chan; /* use just channel */ dibp = dib_unit[chsa]; /* get the DIB pointer */ chp = find_chanp_ptr(chsa); /* find the chanp pointer */ - uptr = find_unit_ptr(chsa); /* find pointer to unit on channel */ +//Z uptr = find_unit_ptr(chsa); /* find pointer to unit on channel */ + uptr = chp->unitptr; /* get the unit ptr */ sim_debug(DEBUG_CMD, &cpu_dev, "rsctlxio 1 chan %04x SPAD %08x\n", chsa, spadent); if (dibp == 0 || uptr == 0) { /* if no dib or unit ptr, CC3 on return */ @@ -1676,7 +1714,7 @@ t_stat rsctlxio(uint16 lchsa, uint32 *status) { /* reset controller XIO */ continue; /* not used */ } chp->chan_status = 0; /* clear the channel status */ - chp->chan_byte = BUFF_NEWCMD; /* no data yet */ + chp->chan_byte = BUFF_EMPTY; /* no data yet */ chp->ccw_addr = 0; /* clear buffer address */ chp->chan_caw = 0x0; /* clear IOCD address */ chp->ccw_count = 0; /* channel byte count 0 bytes*/ @@ -1704,7 +1742,7 @@ 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_NEWCMD; /* no data yet */ + chp->chan_byte = BUFF_EMPTY; /* no data yet */ 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*/ @@ -1720,7 +1758,8 @@ t_stat chan_boot(uint16 chsa, DEVICE *dptr) { sim_debug(DEBUG_XIO, &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_CHNEND; /* done */ +//Z chp->chan_byte = BUFF_CHNEND; /* done */ + chp->chan_byte = BUFF_DONE; /* done with errors */ loading = 0; /* show we are done loading from the boot device */ return SCPE_IOERR; /* return error */ } @@ -1736,16 +1775,16 @@ uint32 cont_chan(uint16 chsa) CHANP *chp = find_chanp_ptr(chsa); /* channel program */ /* we have entries, continue channel program */ -//040129chp->chan_byte == BUFF_NEWCMD) { if (chp->chan_byte != BUFF_NEXT) { /* channel program terminated already, ignore entry */ sim_debug(DEBUG_EXP, &cpu_dev, - "cont_chan chan_byte is BUFF_NEWCMD chsa %04x addr %06x\n", - chsa, chp->ccw_addr); + "cont_chan chan_byte %02x is NOT BUFF_NEXT chsa %04x addr %06x\n", + chp->chan_byte, chsa, chp->ccw_addr); return 1; //040120return SCPE_OK; } if (chp->chan_byte == BUFF_NEXT) { + uint32 chan = get_chan(chsa); sim_debug(DEBUG_EXP, &cpu_dev, "cont_chan resume chan prog chsa %04x iocl %06x\n", chsa, chp->chan_caw); @@ -1758,37 +1797,21 @@ uint32 cont_chan(uint16 chsa) if (chp->chan_status & STATUS_PCHK) { chp->chan_status &= ~STATUS_LENGTH; /* clear incorrect length */ chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* show I/O complete */ -// store_csw(chp); /* store the status in the inch status dw */ -// chp->chan_byte = BUFF_NEWCMD; /* read for new cmd */ - irq_pend = 1; /* show pending int */ + sim_debug(DEBUG_EXP, &cpu_dev, + "cont_chan Error1 FIFO #%1x store_csw CC1 chan %04x status %08x\n", + FIFO_Num(chsa), chan, chp->chan_status); +//?051020 irq_pend = 1; /* show pending int */ return SCPE_OK; /* done */ } /* other error, stop the show */ chp->chan_status &= ~STATUS_PCI; /* remove PCI status bit */ chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* show I/O complete */ - irq_pend = 1; /* show pending int */ + sim_debug(DEBUG_EXP, &cpu_dev, + "cont_chan Error2 FIFO #%1x store_csw CC1 chan %04x status %08x\n", + FIFO_Num(chsa), chan, chp->chan_status); +//?051020 irq_pend = 1; /* show pending int */ return SCPE_OK; /* done */ } -#ifdef XXX - if (chp->chan_status & (STATUS_DEND|STATUS_CEND)) { - sim_debug(DEBUG_EXP, &cpu_dev, - "cont_chan store csw chsa %04x status %08x\n", - chsa, chp->chan_status); -// store_csw(chp); /* store the status in the inch status dw */ - chp->chan_status &= ~STATUS_PCI; /* remove PCI status bit */ - chp->chan_byte = BUFF_NEWCMD; /* we are done */ - irq_pend = 1; /* show pending int */ - return SCPE_OK; /* done, status stored */ - } -#endif -#ifdef XXX - chp->chan_byte = BUFF_NEXT; /* have main pick us up again */ - RDYQ_Put(chsa); /* queue us up */ - sim_debug(DEBUG_EXP, &cpu_dev, - "cont_chan continue wait chsa %04x status %08x\n", - chsa, chp->chan_status); - irq_pend = 1; /* show pending int */ -#endif /* we get here when nothing left to do and status is stored */ sim_debug(DEBUG_EXP, &cpu_dev, "cont_chan continue wait chsa %04x status %08x iocla %06x\n", @@ -1805,7 +1828,7 @@ uint32 cont_chan(uint16 chsa) uint32 scan_chan(uint32 *ilev) { // int i,j; int i; -// uint32 chsa; /* No device */ + uint32 chsa; /* No device */ uint32 chan; /* channel num 0-7f */ uint32 tempa; /* icb address */ uint32 chan_ivl; /* int level table address */ @@ -1823,7 +1846,7 @@ uint32 scan_chan(uint32 *ilev) { dibp = dib_unit[chan]; /* get the IOP/MFP DIB pointer */ if (dibp == 0) return 0; /* skip unconfigured channel */ - /* see if status s stored in FIFO */ + /* see if status is stored in FIFO */ /* see if the FIFO is empty */ if ((FIFO_Num(chan)) && ((FIFO_Get(chan, &sw1) == 0) && (FIFO_Get(chan, &sw2) == 0))) { @@ -1831,19 +1854,7 @@ uint32 scan_chan(uint32 *ilev) { /* we have status to return, do it now */ chp = find_chanp_ptr(chan); /* find the chanp pointer for channel */ tempa = chp->chan_inch_addr; /* get inch status buffer address */ -#ifdef NOTUSED - /* get the address of the interrupt IVL table in main memory */ - chan_ivl = SPAD[0xf1] + (i<<2); /* contents of spad f1 points to chan ivl in mem */ - chan_icba = M[chan_ivl >> 2]; /* get the interrupt context blk addr in memory */ - M[tempa >> 2] = sw1; /* save sa & IOCD address in status WD 1 loc */ - /* save the status to memory */ - M[(tempa+4) >> 2] = sw2; /* save status and count in status WD 2 loc */ - /* now store the status dw address into word 5 of the ICB for the channel */ - /* post sw addr in ICB+5w & set CC2 in SW */ - M[(chan_icba + 20) >> 2] = tempa | BIT1; -// INTS[i] |= INTS_REQ; /* turn on channel interrupt request */ -#endif - chp->chan_byte = BUFF_NEWCMD; /* we are done */ + chp->chan_byte = BUFF_DONE; /* we are done */ 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, sw2); @@ -1856,11 +1867,8 @@ uint32 scan_chan(uint32 *ilev) { if (irq_pend == 0) /* pending int? */ return 0; /* no, done */ if (CPUSTATUS & 0x80) { /* interrupts blocked? */ - irq_pend = 0; /* not pending anymore */ return 0; /* yes, done */ } -// sim_debug(DEBUG_DETAIL, &cpu_dev, -// "scan_chan SPAD[f9] %08x CPUSTATUS %08x\n", SPAD[0xf9], CPUSTATUS); /* ints not blocked, so look for highest requesting interrupt */ for (i=0; i<112; i++) { if (SPAD[i+0x80] == 0) /* not initialize? */ @@ -1879,24 +1887,64 @@ uint32 scan_chan(uint32 *ilev) { /* if there is and the level is not requesting, do it */ /* get the device entry for the logical channel in SPAD */ chan = (SPAD[i+0x80] & 0x7f00); /* get real channel and zero sa */ - dibp = dib_unit[chan]; /* get the device information pointer */ - if (dibp) { /* we have a device to check */ + dibp = dib_chan[get_chan(chan)]; /* get the channel device information pointer */ + if (dibp) { /* we have a channel to check */ /* check for pending status */ -//TRY031820 if (FIFO_Num(chan) && ((INTS[i] & INTS_REQ) == 0)) { - if (FIFO_Num(chan)) { - chp = find_chanp_ptr(chan); /* find the chanp pointer for channel */ + if (FIFO_Num(chan) && ((INTS[i] & INTS_REQ) == 0)) { + /* new 051020 find actual device with the channel program */ + /* not the channel, that is not correct most of the time */ +/*new051020*/ tempa = dibp->chan_fifo[dibp->chan_fifo_out]; /* get SW1 of FIFO entry */ +/*new051020*/ chsa = chan | (tempa >> 24); /* find device address for requesting chan prog */ +//OLD051020 chp = find_chanp_ptr(chan); /* find the chanp pointer for channel */ +/*new051020*/ chp = find_chanp_ptr(chsa); /* find the chanp pointer for channel */ tempa = chp->chan_inch_addr; /* get inch status buffer address */ chan_ivl = SPAD[0xf1] + (i<<2); /* contents of spad f1 points to chan ivl in mem */ chan_icba = RMW(chan_ivl); /* get the interrupt context block addr in memory */ -#ifdef TRY032820 INTS[i] |= INTS_REQ; /* turn on channel interrupt request */ -#else - if (INTS[i] & INTS_ENAB) - INTS[i] |= INTS_REQ; /* turn on channel interrupt request */ -#endif sim_debug(DEBUG_IRQ, &cpu_dev, - "scan_chan %04x READ FIFO #%1x irq %02x inch %06x chan_icba %06x\n", - chan, FIFO_Num(chan), i, tempa, chan_icba); + "scan_chan %04x LOOK FIFO #%1x irq %02x inch %06x chsa %04x chan_icba %06x chan_byte %02x\n", + chan, FIFO_Num(chan), i, tempa, chsa, chan_icba, chp->chan_byte); +#ifndef DO_ACTIVATE_NOW_051920 + /* requesting, make active and turn off request flag */ + INTS[i] &= ~INTS_REQ; /* turn off request */ + INTS[i] |= INTS_ACT; /* turn on active */ + SPAD[i+0x80] |= SINT_ACT; /* show active in SPAD too */ + /* get the address of the interrupt IVL table in main memory */ + chan_ivl = SPAD[0xf1] + (i<<2); /* contents of spad f1 points to chan ivl in mem */ + chan_icba = RMW(chan_ivl); /* get the interrupt context block addr in memory */ + + sim_debug(DEBUG_IRQ, &cpu_dev, + "scan_chanx INTS REQ irq %02x found chan_icba %08x INTS %08x\n", + i, chan_icba, INTS[i]); + sim_debug(DEBUG_IRQ, &cpu_dev, + "scan_chanx Last OPSD1 %08x OPSD2 %08x NPSD1 %08x NPSD2 %08x\n", + RMW(chan_icba), RMW(chan_icba+4), RMW(chan_icba+8), RMW(chan_icba+12)); + + *ilev = i; /* return interrupt level */ + irq_pend = 0; /* not pending anymore */ + /* the dibp pointer will be zero if no FIFO status is available */ + /* at this point this level can become active */ + /* this level is enabled and already requesting */ + tempa = chp->chan_inch_addr; /* get inch status buffer address */ + /* see if the FIFO is empty or has status to post */ + /* FIFO is not empty, so post status and make interrupt active */ + /* the channel is not busy, see if any status to post */ + if (post_csw(chp, 0)) { + sim_debug(DEBUG_IRQ, &cpu_dev, + "scan_chanx %04x POST FIFO #%1x irq %02x inch %06x chan_icba %06x chan_byte %02x\n", + chan, FIFO_Num(chan), i, chp->chan_inch_addr, chan_icba, chp->chan_byte); + } else { + sim_debug(DEBUG_IRQ, &cpu_dev, + "scan_chanx %04x NOT POSTED FIFO #%1x irq %02x inch %06x chan_icba %06x chan_byte %02x\n", + chan, FIFO_Num(chan), i, chp->chan_inch_addr, chan_icba, chp->chan_byte); + } + return(chan_icba); /* return ICB address */ +#endif + } else { + dibp = 0; /* no status, so can not post */ +// sim_debug(DEBUG_IRQ, &cpu_dev, +// "scan_chan %04x WAIT FIFO #%1x Nothing to do irq %02x INTS[i] %08x\n", +// chan, FIFO_Num(chan), i, INTS[i]); } } /* look for the highest requesting interrupt */ @@ -1916,28 +1964,36 @@ uint32 scan_chan(uint32 *ilev) { "scan_chan INTS REQ irq %02x found chan_icba %08x INTS %08x\n", i, chan_icba, INTS[i]); sim_debug(DEBUG_IRQ, &cpu_dev, - "scan_chan OPSD1 %08x OPSD2 %08x NPSD1 %08x NPSD2 %08x\n", + "scan_chan Last OPSD1 %08x OPSD2 %08x NPSD1 %08x NPSD2 %08x\n", RMW(chan_icba), RMW(chan_icba+4), RMW(chan_icba+8), RMW(chan_icba+12)); *ilev = i; /* return interrupt level */ irq_pend = 0; /* not pending anymore */ +#ifdef DO_ACTIVATE_NOW_051920 + /* the dibp pointer will be zero if no FIFO status is available */ /* at this point this level can become active */ /* this level is enabled and already requesting */ if (dibp) { /* we have a device to check */ - chp = find_chanp_ptr(chan); /* find the chanp pointer for channel */ + /* this code changed 051020 to use actual channel prog pointer for device */ + /* not the channel. Code above already has correct chp pointer */ +//OLD051020 chp = find_chanp_ptr(chan); /* find the chanp pointer for channel */ tempa = chp->chan_inch_addr; /* get inch status buffer address */ /* see if the FIFO is empty or has status to post */ - /* fifo is not empty, so post status and make interrupt active*/ + /* FIFO is not empty, so post status and make interrupt active */ /* the channel is not busy, see if any status to post */ if (post_csw(chp, 0)) { sim_debug(DEBUG_IRQ, &cpu_dev, - "scan_chan %04x POST FIFO #%1x irq %02x inch %06x chan_icba %06x\n", - chan, FIFO_Num(chan), i, chp->chan_inch_addr, chan_icba); - } else + "scan_chan %04x POST FIFO #%1x irq %02x inch %06x chan_icba %06x chan_byte %02x\n", + chan, FIFO_Num(chan), i, chp->chan_inch_addr, chan_icba, chp->chan_byte); + } else { sim_debug(DEBUG_IRQ, &cpu_dev, - "scan_chan %04x NOT POSTED FIFO #%1x irq %02x inch %06x chan_icba %06x\n", - chan, FIFO_Num(chan), i, chp->chan_inch_addr, chan_icba); - } else { + "scan_chan %04x NOT POSTED FIFO #%1x irq %02x inch %06x chan_icba %06x chan_byte %02x\n", + chan, FIFO_Num(chan), i, chp->chan_inch_addr, chan_icba, chp->chan_byte); + } + } + else +#endif + { sim_debug(DEBUG_IRQ, &cpu_dev, "scan_chan %04x POST NON FIFO irq %02x chan_icba %06x SPAD[%02x] %08x\n", chan, i, chan_icba, i+0x80, SPAD[i+0x80]); @@ -2029,7 +2085,7 @@ t_stat chan_set_devs() { chp->ccw_flags = 0; /* Command chain and supress incorrect length */ chp->ccw_cmd = 0; /* read command */ chp->chan_inch_addr = 0; /* clear address of stat dw in memory */ -#ifndef OLD_CHAN + if ((uptr->flags & UNIT_DIS) == 0) { /* is unit marked disabled? */ /* see if this is unit zero */ if ((chsa & 0xff) == 0) { @@ -2070,17 +2126,6 @@ t_stat chan_set_devs() { dib_unit[chsa] = dibp; /* no, save the dib address */ } } -#else - if ((uptr->flags & UNIT_DIS) == 0) { /* is unit marked disabled? */ - if ((dptr->flags & DEV_CHAN) == 0) { - if (dib_unit[chsa] != 0) { - printf("Channel/SubAddress %04x multiply defined, aborting\n", chsa); - return SCPE_IERR; /* no, arg error */ - } - } - dib_unit[chsa] = dibp; /* no, save the dib address */ - } -#endif if (dibp->dev_ini != NULL) /* call channel init if defined */ dibp->dev_ini(uptr, 1); /* init the channel */ uptr++; /* next UNIT pointer */ diff --git a/SEL32/sel32_clk.c b/SEL32/sel32_clk.c index c16781f..a14b964 100644 --- a/SEL32/sel32_clk.c +++ b/SEL32/sel32_clk.c @@ -49,6 +49,8 @@ extern int irq_pend; /* go scan for pending int or I/O */ extern uint32 INTS[]; /* interrupt control flags */ extern uint32 SPAD[]; /* computer SPAD */ extern uint32 M[]; /* system memory */ +extern uint32 outbusy; /* output waiting on timeout */ +extern uint32 inbusy; /* input waiting on timeout */ int32 rtc_pie = 0; /* rtc pulse ie */ int32 rtc_tps = 60; /* rtc ticks/sec */ @@ -135,16 +137,15 @@ t_stat rtc_srv (UNIT *uptr) (((INTS[rtc_lvl] & INTS_ACT) == 0) || /* and not active */ ((SPAD[rtc_lvl+0x80] & SINT_ACT) == 0))) { /* in spad too */ //DIAGHELP INTS[rtc_lvl] |= INTS_REQ; /* request the interrupt */ + if ((outbusy==0) && (inbusy==0)) /* skip interrupt if con I/O in busy wait */ INTS[rtc_lvl] |= INTS_REQ; /* request the interrupt */ irq_pend = 1; /* make sure we scan for int */ } } #define FOR_MIKE -#ifdef FOR_MIKE +#ifndef FOR_MIKE //Mike rtc_unit.wait = sim_rtcn_calb (rtc_tps, TMR_RTC); /* calibrate */ rtc_unit.wait = sim_rtcn_calb (rtc_tps, TMR_RTC); /* calibrate */ -#else - rtc_unit.wait = sim_rtcn_calb (rtc_tps, TMR_RTC); /* calibrate */ #endif sim_activate_after (&rtc_unit, 1000000/rtc_tps);/* reactivate 16666 tics / sec */ return SCPE_OK; @@ -190,11 +191,9 @@ t_stat rtc_reset(DEVICE *dptr) { rtc_pie = 0; /* disable pulse */ /* initialize clock calibration */ -#ifdef FOR_MIKE +#ifndef FOR_MIKE //Mike rtc_unit.wait = sim_rtcn_init_unit(&rtc_unit, rtc_unit.wait, TMR_RTC); rtc_unit.wait = sim_rtcn_init_unit(&rtc_unit, rtc_unit.wait, TMR_RTC); -#else - rtc_unit.wait = sim_rtcn_init_unit(&rtc_unit, rtc_unit.wait, TMR_RTC); #endif sim_activate (&rtc_unit, rtc_unit.wait); /* activate unit */ return SCPE_OK; @@ -269,7 +268,7 @@ const char *itm_desc(DEVICE *dptr); #ifdef FOR_MIKE /* Mike suggested I remove the UNIT_IDLE flag from ITM. This causes SEL32 */ -/* to use 100% of the CPU instead of waiting amd ruinning 10% cpu usage */ +/* to use 100% of the CPU instead of waiting and running 10% cpu usage */ //BAD Mike UNIT itm_unit = { UDATA (&itm_srv, 0, 0), 26042, UNIT_ADDR(0x7F04)}; UNIT itm_unit = { UDATA (&itm_srv, 0, 0), 26042, UNIT_ADDR(0x7F04)}; #else diff --git a/SEL32/sel32_com.c b/SEL32/sel32_com.c index a43e573..7d3cd49 100644 --- a/SEL32/sel32_com.c +++ b/SEL32/sel32_com.c @@ -237,8 +237,8 @@ MTAB com_mod[] = { }; UNIT com_unit[] = { -// {UDATA(&comi_srv, UNIT_ATTABLE|UNIT_IDLE, 0), COM_WAIT, UNIT_ADDR(0x0000)}, /* 0 */ - {UDATA(&comi_srv, UNIT_ATTABLE|UNIT_IDLE, 0), COM_WAIT, UNIT_ADDR(0x4747)}, /* dummy */ + {UDATA(&comi_srv, UNIT_ATTABLE|UNIT_IDLE, 0), COM_WAIT, UNIT_ADDR(0x0000)}, /* 0 */ +// {UDATA(&comi_srv, UNIT_ATTABLE|UNIT_IDLE, 0), COM_WAIT, UNIT_ADDR(0x4747)}, /* dummy */ }; //DIB com_dib = {NULL, com_startcmd, NULL, NULL, com_ini, com_unit, com_chp, COM_UNITS, 0x0f, 0x7e00, 0, 0, 0}; @@ -261,9 +261,9 @@ DIB com_dib = { }; REG com_reg[] = { - { BRDATAD (STA, com_sta, 16, 8, COM_LINES, "status buffers, lines 0 to 8") }, - { BRDATAD (RBUF, com_rbuf, 16, 8, COM_LINES, "input buffer, lines 0 to 8") }, - { BRDATAD (XBUF, com_xbuf, 16, 8, COM_LINES, "output buffer, lines 0 to 8") }, + { BRDATAD (STA, com_sta, 16, 8, COM_LINES, "status buffers, lines 0 to 7") }, + { BRDATAD (RBUF, com_rbuf, 16, 8, COM_LINES, "input buffer, lines 0 to 7") }, + { BRDATAD (XBUF, com_xbuf, 16, 8, COM_LINES, "output buffer, lines 0 to 7") }, { ORDATAD (SCAN, com_scan, 6, "scanner line number") }, { FLDATAD (SLCK, com_slck, 0, "scanner lock") }, { DRDATA (TPS, com_tps, 8), REG_HRO}, diff --git a/SEL32/sel32_con.c b/SEL32/sel32_con.c index 5a299fd..1bd603d 100644 --- a/SEL32/sel32_con.c +++ b/SEL32/sel32_con.c @@ -96,6 +96,9 @@ struct _con_data con_data[NUM_UNITS_CON]; uint32 atbuf=0; /* attention buffer */ +uint32 outbusy = 0; /* output waiting on timeout */ +uint32 inbusy = 0; /* input waiting on timeout */ +uint32 inskip = 0; /* last wait was on clock */ /* forward definitions */ uint16 con_preio(UNIT *uptr, uint16 chan); @@ -212,7 +215,7 @@ uint16 con_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) { uptr->CMD |= (cmd & CON_MSK); /* save command */ uptr->SNS = SNS_RDY|SNS_ONLN; /* status is online & ready */ if (unit == 1) -/*#*/ sim_activate(uptr, 40); /* start us off */ +/*#*/ sim_activate(uptr, 30); /* start us off */ //@41 sim_activate(uptr, 40); /* start us off */ return 0; /* no status change */ break; @@ -293,6 +296,9 @@ uint16 con_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) { static uint32 last2 = 0; #endif +#ifdef TRYTHIS +extern uint32 INTS[]; +#endif /* Handle output transfers for console */ t_stat con_srvo(UNIT *uptr) { uint16 chsa = GET_UADDR(uptr->CMD); @@ -347,6 +353,42 @@ t_stat con_srvo(UNIT *uptr) { } if ((cmd == CON_WR) || (cmd == CON_RWD)) { +#ifndef SLOW_WAY + int cnt = 0; + +#ifdef TRYTHIS_DIDNOT_WORK + if (INTS[0x18] & INTS_ACT) /* if clock int active, wait */ + return sim_activate (uptr, 30); /* come back real soon */ +#endif + + /* see if write complete */ + if (uptr->CMD & CON_OUTPUT) { + /* write is complete, post status */ + sim_debug(DEBUG_CMD, &con_dev, + "con_srvo write CMD %08x chsa %04x cmd %02x complete\n", + uptr->CMD, chsa, cmd); + uptr->CMD &= LMASK; /* nothing left, command complete */ + + outbusy = 0; /* output done */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* done */ + return SCPE_OK; + } + /* Write to device */ + while (chan_read_byte(chsa, &ch) == SCPE_OK) { /* get byte from memory */ + /* HACK HACK HACK */ + ch &= 0x7f; /* make 7 bit w/o parity */ + sim_putchar(ch); /* output next char to device */ + cnt++; /* count chars output */ + } + uptr->CMD |= CON_OUTPUT; /* output command complete */ + sim_debug(DEBUG_CMD, &con_dev, + "con_srvo write wait %03x CMD %08x chsa %04x cmd %02x to complete\n", +// 23*cnt+29, uptr->CMD, chsa, cmd); + 19*cnt+23, uptr->CMD, chsa, cmd); + sim_activate(uptr, 19*cnt+23); /* wait for a while */ + outbusy = 1; /* output waiting */ + +#else /* SLOW_WAY */ /* Write to device */ if (chan_read_byte(chsa, &ch)) { /* get byte from memory */ uptr->CMD &= LMASK; /* nothing left, command complete */ @@ -385,9 +427,13 @@ t_stat con_srvo(UNIT *uptr) { #else /* do not output to debug file */ sim_putchar(ch); /* output next char to device */ + sim_debug(DEBUG_CMD, &con_dev, + "con_srvo write %01x: CMD %08x putch 0x%02x\n", unit, uptr->CMD, ch); #endif sim_activate(uptr, 30); /* start us off */ +// sim_activate(uptr, 20); /* start us off */ } +#endif /* SLOW_WAY */ } return SCPE_OK; } @@ -452,9 +498,14 @@ t_stat con_srvi(UNIT *uptr) { case CON_RD: /* 0x02 */ /* read from device */ case CON_ECHO: /* 0x0a */ /* read from device w/ECHO */ +#ifdef TRYTHIS_DIDNOTWORK + if (INTS[0x18] & INTS_ACT) /* if clock int active, wait */ + return sim_activate (uptr, 30); /* come back real soon */ +#endif if ((uptr->u4 != con_data[unit].incnt) || /* input empty */ (uptr->CMD & CON_INPUT)) { /* input waiting? */ +//try051920 inbusy = 1; /* tell clock we are busy */ // if (uptr->CMD & CON_INPUT) { /* input waiting? */ ch = con_data[unit].ibuff[uptr->u4]; /* get char from read buffer */ sim_debug(DEBUG_CMD, &con_dev, @@ -471,6 +522,7 @@ t_stat con_srvi(UNIT *uptr) { "con_srvi write error unit %02x: CMD %08x read %02x u4 %02x ccw_count %02x\n", unit, uptr->CMD, ch, uptr->u4, chp->ccw_count); uptr->CMD &= LMASK; /* nothing left, command complete */ +//try051920 inbusy = 0; /* tell clock we are not busy */ chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* we done */ break; } @@ -492,6 +544,7 @@ t_stat con_srvi(UNIT *uptr) { /* user wants more, look next time */ if (uptr->u4 == con_data[unit].incnt) { /* input empty */ uptr->CMD &= ~CON_INPUT; /* no input available */ +//try051920 inbusy = 0; /* tell clock we are not busy */ } break; } @@ -504,6 +557,7 @@ t_stat con_srvi(UNIT *uptr) { if (uptr->u4 != con_data[unit].incnt) { /* input empty */ uptr->CMD |= CON_INPUT; /* input still available */ } +//try051920 inbusy = 0; /* tell clock we are not busy */ chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* we done */ break; } @@ -511,6 +565,11 @@ t_stat con_srvi(UNIT *uptr) { break; } + if (inskip == 0) { + inskip = 1; + return sim_activate (uptr, 30); /* come back real soon */ + } + inskip = 1; /* check for next input if reading or @@A sequence */ r = sim_poll_kbd(); /* poll for a char */ if (r & SCPE_KFLAG) { /* got a char */ @@ -606,8 +665,9 @@ t_stat con_srvi(UNIT *uptr) { unit, uptr->CMD, ch, uptr->u4, con_data[unit].incnt); } goout: -// return sim_activate (uptr, 5000); - return tmxr_clock_coschedule_tmr (uptr, TMR_RTC, 1); /* come back soon */ +// return sim_activate (uptr, 5000); + tmxr_clock_coschedule_tmr(uptr, TMR_RTC, 1); /* come back soon */ + return SCPE_OK; } t_stat con_reset(DEVICE *dptr) { @@ -631,13 +691,13 @@ uint16 con_haltio(UNIT *uptr) { // 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_flags = 0; /* stop any chaining */ - chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITEXP); /* force error */ uptr->CMD &= LMASK; /* make non-busy */ uptr->u4 = 0; /* no I/O yet */ con_data[unit].incnt = 0; /* no input data */ uptr->SNS = SNS_RDY|SNS_ONLN; /* status is online & ready */ sim_debug(DEBUG_CMD, &con_dev, "con_haltio HIO I/O stop chsa %04x cmd = %02x\n", chsa, cmd); + chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITEXP); /* force error */ return SCPE_IOERR; } uptr->u4 = 0; /* no I/O yet */ diff --git a/SEL32/sel32_cpu.c b/SEL32/sel32_cpu.c index 2937864..4241369 100644 --- a/SEL32/sel32_cpu.c +++ b/SEL32/sel32_cpu.c @@ -171,10 +171,10 @@ uint32 GPR[8]; /* General Purpose Registers */ uint32 BR[8]; /* Base registers */ uint32 PC; /* Program counter */ uint32 CC; /* Condition codes, bits 1-4 of PSD1 */ -uint32 SPAD[256]; /* Scratch pad memory */ -uint32 INTS[112]; /* Interrupt status flags */ uint32 CPUSTATUS; /* cpu status word */ uint32 TRAPSTATUS; /* trap status word */ +uint32 SPAD[256]; /* Scratch pad memory */ +uint32 INTS[112]; /* Interrupt status flags */ uint32 CMCR; /* Cache Memory Control Register */ uint32 SMCR; /* Shared Memory Control Register */ uint32 CMSMC; /* V9 Cache/Shadow Memory Configuration */ @@ -218,7 +218,7 @@ uint32 TRAPME = 0; /* trap to be executed */ uint32 attention_trap = 0; /* set when trap is requested */ uint32 RDYQIN; /* fifo input index */ -uint32 RDYQOUT; /* fifo ooutput index */ +uint32 RDYQOUT; /* fifo output index */ uint32 RDYQ[128]; /* channel ready queue */ uint8 waitqcnt = 0; /* # instructions before start */ @@ -267,6 +267,8 @@ extern int irq_pend; /* go scan for pending i extern void rtc_setup(uint32 ss, uint32 level); /* tell rtc to start/stop */ extern void itm_setup(uint32 ss, uint32 level); /* tell itm to start/stop */ extern int32 itm_rdwr(uint32 cmd, int32 cnt, uint32 level); /* read/write the interval timer */ +extern int16 post_csw(CHANP *chp, uint32 rstat); +extern DIB *dib_chan[MAX_CHAN]; /* floating point subroutines definitions */ extern uint32 s_fixw(uint32 val, uint32 *cc); @@ -1925,56 +1927,51 @@ uint32 drop_nop = 0; /* Set if right hw instruction i 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 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 */ + 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 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 skipinstr = 0; /* Skip test for interrupt on this instruction */ -//@@uint32 drop_nop = 0; /* Set if right hw instruction is a nop */ - uint32 int_icb; /* interrupt context block address */ -//@@uint32 OIR=0; /* Original Instruction register */ -//@@uint32 OPSD1=0; /* Original PSD1 */ -//@@uint32 OPSD2=0; /* Original PSD2 */ - uint32 TPSD[2]; /* Temp PSD */ - uint32 rstatus; /* temp return status */ - int32 int32a; /* temp int */ - int32 int32b; /* temp int */ - int32 int32c; /* temp int */ + 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 DO_DYNAMIC_DEBUG int32 event = 0; #endif wait_loop: while (reason == 0) { /* loop until halted */ -#ifdef OLDCODE + // wait_loop: if (sim_interval <= 0) { /* event queue? */ reason = sim_process_event(); /* process */ @@ -1994,16 +1991,6 @@ wait_loop: } sim_interval--; /* count down */ -#else - // wait_loop: - if (sim_interval <= 0) { /* event queue? */ - reason = sim_process_event(); /* process events */ - if (reason != SCPE_OK) { - break; /* process */ - } - } - sim_interval--; /* count down */ -#endif if (drop_nop) { /* need to drop a nop? */ PSD1 = (PSD1 + 2) | (((PSD1 & 2) >> 1) & 1); /* skip this instruction */ @@ -2022,33 +2009,45 @@ wait_loop: } /* process any channel programs */ - if (RDYQ_Num()) { +//mm if (RDYQ_Num()) { + if (RDYQ_Num() && (skipinstr == 0)) { uint32 chsa; /* channel/sub adddress */ int32 stat; /* return status 0/1 from loadccw */ if (waitqcnt == 0) { +//TRY051020 if ((waitqcnt == 0) && (irq_auto == 0)) { /* we have entries, continue channel program */ if (RDYQ_Get(&chsa) == SCPE_OK) { /* get chsa for program */ - sim_debug(DEBUG_IRQ, &cpu_dev, + sim_debug(DEBUG_XIO, &cpu_dev, "CPU RDYQ entry for chsa %04x starting\n", chsa); stat = cont_chan(chsa); /* resume the channel program */ if (stat) - sim_debug(DEBUG_IRQ, &cpu_dev, + sim_debug(DEBUG_XIO, &cpu_dev, "CPU RDYQ entry for chsa %04x processed\n", chsa); } - waitqcnt = 20; /* wait 10 instructions */ -// waitqcnt = 50; /* wait 10 instructions */ + /* NOTE! This wait instruction count can not be larger than 30 */ + /* for UTX. UTX will fail trying to write to device disk 0801 */ + waitqcnt = 35; /* wait 10 instructions */ +// waitqcnt = 20; /* wait 10 instructions */ +//BAD4UTX waitqcnt = 50; /* wait 10 instructions */ +//BAD4UTX waitqcnt = 70; /* wait 10 instructions */ +// waitqcnt = 30; /* wait 10 instructions */ } else waitqcnt -= 1; /* wait another instruction */ } else -// waitqcnt = 50; /* wait 10 instructions */ - waitqcnt = 20; /* wait 10 instructions */ + waitqcnt = 35; /* wait 10 instructions */ +// waitqcnt = 30; /* wait 10 instructions */ +//BAD4UTX waitqcnt = 70; /* wait 10 instructions */ +//BAD4UTX waitqcnt = 50; /* wait 10 instructions */ +// waitqcnt = 20; /* wait 10 instructions */ //040120 waitqcnt = 10; /* wait 10 instructions */ -// + + /* process pending I/O interrupts */ -/*AIR*/ if (!loading && (irq_auto==0) && (wait4int || irq_pend)) { /* see if ints are pending */ +//AIR*/ if (!loading && (irq_auto==0) && (wait4int || irq_pend)) { /* see if ints are pending */ +/*AIR*/ if (!loading && (irq_auto==0) && (irq_pend)) { /* see if ints are pending */ uint32 ilev; SPAD[0xf9] = CPUSTATUS; /* save the cpu status in SPAD */ int_icb = scan_chan(&ilev); /* no, go scan for I/O int pending */ @@ -2058,11 +2057,6 @@ wait_loop: "<|>Normal int return icb %06x level %02x irq_pend %1x wait4int %1x\n", int_icb, il, irq_pend, wait4int); -#ifdef DO_DYNAMIC_DEBUG - /* start debugging on first clock tick */ - if (il == 0x18) - cpu_dev.dctrl |= (DEBUG_INST | DEBUG_TRAP | DEBUG_EXP | DEBUG_IRQ); -#endif /* take interrupt, store the PSD, fetch new PSD */ bc = PSD2 & 0x3ff8; /* get copy of cpix */ M[int_icb>>2] = PSD1&0xfffffffe; /* store PSD 1 */ @@ -2100,11 +2094,13 @@ wait_loop: /* if this is F class I/O interrupt, clear the active level */ /* SPAD entries for interrupts begin at 0x80 */ /*AIR*/ irq_auto = il; /* show processing in blocked mode */ +#ifndef LEAVE_ACT_051020 INTS[il] &= ~INTS_ACT; /* deactivate specified int level */ SPAD[il+0x80] &= ~SINT_ACT; /* deactivate in SPAD too */ +#endif sim_debug(DEBUG_IRQ, &cpu_dev, - "<|>Auto-reset interrupt INTS[%02x] %08x SPAD[%02x] %08x\n", - il, INTS[il], il+0x80, SPAD[il+0x80]); + "<|>Auto-reset interrupt INTS[%02x] %08x SPAD[%02x] %08x simi %02x\n", + il, INTS[il], il+0x80, SPAD[il+0x80], sim_interval); /*TRY*/ } } else { sim_debug(DEBUG_IRQ, &cpu_dev, @@ -2197,7 +2193,6 @@ wait_loop: skipi: i_flags = 0; /* do not update pc if MF or NPM */ -//XXX skipinstr = 0; /* skip only once */ TRAPSTATUS = CPUSTATUS & 0x57; /* clear all trap status except cpu type */ /* fill IR from logical memory address */ @@ -2235,7 +2230,6 @@ skipi: IR <<= 16; /* put instruction in left hw */ if ((CPU_MODEL <= MODEL_27) || (CPU_MODEL == MODEL_87) || (CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9)) { -//WAS032120 skipinstr = 0; /* only test this once */ #ifndef NOTNOW if (skipinstr) sim_debug(DEBUG_IRQ, &cpu_dev, @@ -2249,14 +2243,12 @@ skipi: if (IR == 0x00020000) { /* is this a NOP from rt hw? */ PSD1 = (PSD1 + 2) | (((PSD1 & 2) >> 1) & 1); /* skip this instruction */ // fprintf(stderr, "RIGHT HW skip NOP instr %x skip nop at %x\n", IR, PSD1); -//WAS032120 skipinstr = 0; /* only test this once */ 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 */ } -//WAS032120 skipinstr = 0; /* only test this once */ if (skipinstr) sim_debug(DEBUG_IRQ, &cpu_dev, "3Rt HW instruction skipinstr %1x is set PSD1 %08x PSD2 %08x CPUSTATUS %08x\n", @@ -2789,6 +2781,7 @@ exec: "<|>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 */ +/*051920*/ skipinstr = 1; /* skip interrupt test */ } } CPUSTATUS &= ~0x80; /* into status word bit 24 too */ @@ -3889,6 +3882,7 @@ skipit: 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 */ +/*051920*/ skipinstr = 1; /* skip interrupt test */ } } } @@ -3943,6 +3937,7 @@ skipit: if ((opr & 0xF) == 0x3) { addr = NEGATE32(addr); /* subtract, so negate source */ } +#ifdef NO_NORMALIZE // temp2 = s_adfw(temp, addr, &CC); /* add float numbers */ // } else { /* handle add */ // } @@ -3973,6 +3968,7 @@ skipit: } } else +#endif temp2 = s_adfw(temp, addr, &CC); /* do ADFW */ sim_debug(DEBUG_EXP, &cpu_dev, "%s GPR[%d] %08x addr %08x result %08x CC %08x\n", @@ -4125,6 +4121,7 @@ skipit: if ((opr & 0xF) == 0xb) { td = NEGATE32(td); /* make negative for subtract */ } +#ifdef NO_NORMALIZE if (td == 0) { /* is reg value zero */ dest = s_normfd(source, &CC); /* normalize addr value */ if (CC & CC1BIT) { @@ -4151,6 +4148,7 @@ skipit: } } else +#endif dest = s_adfd(td, source, &CC); /* do ADFD */ sim_debug(DEBUG_EXP, &cpu_dev, @@ -5558,6 +5556,7 @@ doovr2: "<|>IntX deactivate level %02x at SVC #%2x PSD1 %08x\n", irq_auto, temp2, PSD1); /*AIR*/ irq_auto = 0; /* show done processing in blocked mode */ +/*051920*/ skipinstr = 1; /* skip interrupt test */ } } } @@ -5768,6 +5767,7 @@ doovr2: if ((opr & 8) == 0) { /* Was it SUFW? */ addr = NEGATE32(addr); /* take negative for add */ } +#ifdef NO_NORMALIZE // if (opr & 8) { /* Was it ADFW? */ /* test for zero reg value */ // if ((temp2 == 0) && ((addr & 0x80000000) == 0)) { /* is reg value zero */ @@ -5798,6 +5798,7 @@ doovr2: } } else +#endif temp = s_adfw(temp2, addr, &CC); /* do ADFW */ // } else { // /* s_sufw will negate the value before calling add */ @@ -5832,6 +5833,7 @@ doovr2: if ((opr & 8) == 0) { /* Was it SUFD? */ td = NEGATE32(td); /* make negative for subtract */ } +#ifdef NO_NORMALIZE /* test for zero reg value */ // if ((td == 0) && ((GPR[reg] & 0x80000000) == 0)) { /* is reg value zero */ if (td == 0) { /* is reg value zero */ @@ -5860,6 +5862,7 @@ doovr2: } } else +#endif dest = s_adfd(td, source, &CC); /* do ADFD */ // } else { // /* s_sufd will negate the memory value before calling add */ @@ -6251,6 +6254,7 @@ doovr2: sim_debug(DEBUG_IRQ, &cpu_dev, "<|>IntX deactivate level %02x at LPSD(CM) %08x\n", irq_auto, PSD1); /*AIR*/ irq_auto = 0; /* show done processing in blocked mode */ +/*051920*/ skipinstr = 1; /* skip interrupt test */ } } } @@ -6321,7 +6325,7 @@ doovr2: /* 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 eror */ + /* 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 */ @@ -6441,7 +6445,7 @@ doovr2: 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 */ -//?? uint32 maxlev = 0x6f; /* 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 */ @@ -6450,12 +6454,14 @@ doovr2: if (CPU_MODEL <= MODEL_27) { maxlev = 0x6f; /* 27 uses 112 */ } -// if (CPU_MODEL == MODEL_V9) { -// maxlev = 0x5f; /* 27 uses 112 */ -// } switch(opr & 0x7) { /* use bits 13-15 to determine instruction */ case 0x0: /* EI FC00 Enable Interrupt */ +#ifdef DO_DYNAMIC_DEBUG + if (prior >= 0x6f) + /* start debugging */ + cpu_dev.dctrl |= (DEBUG_INST | DEBUG_CMD | DEBUG_EXP | DEBUG_IRQ | DEBUG_TRAP); +#endif if (prior > maxlev) /* ignore for invalid levels */ break; /* ignore */ /* SPAD entries for interrupts begin at 0x80 */ @@ -6513,8 +6519,8 @@ doovr2: } //DIAGS if ((SPAD[prior+0x80] & 0x0f807fff) == 0x03007f04) { if ((SPAD[prior+0x80] & 0x0f00ffff) == 0x03007f04) { - itm_setup(0, prior); /* tell timer to stop */ sim_debug(DEBUG_IRQ, &cpu_dev, "Intv Timer DI %02x Turn off\n", prior); + itm_setup(0, prior); /* tell timer to stop */ } break; @@ -6662,14 +6668,6 @@ doovr2: temp2 = (IR & 0x7fff) + (GPR[reg] & 0x7fff); /* set new chan/suba into IR */ else temp2 = (IR & 0x7fff); /* set new chan/suba into IR */ -#ifdef DO_DYNAMIC_DEBUG - if ((temp2 & 0xff) == 1) - /* start debugging */ - cpu_dev.dctrl |= (DEBUG_INST | DEBUG_CMD | DEBUG_EXP | DEBUG_IRQ); -#else - if ((temp2 & 0xff) == 1) - temp &= ~1; -#endif lchan = (temp2 & 0x7F00) >> 8; /* get 7 bit logical channel address */ suba = temp2 & 0xFF; /* get 8 bit subaddress */ /* the channel must be defined as a class F I/O channel in SPAD */ @@ -6698,8 +6696,8 @@ doovr2: "$$ 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 OP %02x\n", - rchsa, PSD1, PSD2, IR, OP); + "$$ 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 */ @@ -6721,11 +6719,6 @@ mcheck: goto mcheck; /* bad iocl address */ } -#ifdef DO_DYNAMIC_DEBUG - if (RMW(temp) == 0x010be015) - /* start debugging */ - cpu_dev.dctrl |= (DEBUG_INST | DEBUG_CMD | DEBUG_EXP | DEBUG_IRQ); -#endif sim_debug(DEBUG_XIO, &cpu_dev, "XIO rdy PSD1 %08x chan %02x irq %02x icb %06x iocla %06x iocd1 %08x iocd2 %08x\n", PSD1, chan, ix, addr, addr+16, RMW(temp), RMW(temp+4)); @@ -6791,10 +6784,6 @@ mcheck: sim_debug(DEBUG_XIO, &cpu_dev, "XIO TIO ret PSD1 %08x chsa %04x status %08x spad %08x INTS[%02x] %08x BLK %1x\n", PSD1, rchsa, rstatus, t, ix, INTS[ix], CPUSTATUS&0x80?1:0); -#ifdef DO_DYNAMIC_DEBUG - /* start debugging */ - cpu_dev.dctrl |= (DEBUG_INST | DEBUG_CMD | DEBUG_EXP | DEBUG_IRQ); -#endif break; case 0x04: /* Stop I/O STPIO */ @@ -6851,16 +6840,16 @@ mcheck: case 0x0C: /* Enable channel interrupt ECI */ /* disable int only */ + sim_debug(DEBUG_XIO, &cpu_dev, "ECI entry chan %04x suba %04x\n", chan, suba); sim_debug(DEBUG_XIO, &cpu_dev, - "XIO ECI chan %04x sa %04x spad %08x INTS[%02x] %08x\n", - chan, suba, t, ix, INTS[ix]); -#ifdef DO_DYNAMIC_DEBUG - if (t == 0x0f727e00) - /* start debugging */ - cpu_dev.dctrl |= (DEBUG_INST | DEBUG_CMD | DEBUG_EXP | DEBUG_IRQ); -#endif + "XIO ECI rchsa %04x spad %08x INTS[%02x] %08x\n", + rchsa, t, ix, INTS[ix]); + if ((TRAPME = checkxio(rchsa, &rstatus))) goto newpsd; /* error returned, trap cpu */ + sim_debug(DEBUG_XIO, &cpu_dev, + "ECI after checkxio chan %04x suba %04x status %08x\n", chan, suba, 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 */ @@ -6874,8 +6863,24 @@ mcheck: sim_debug(DEBUG_XIO, &cpu_dev, "XIO DCI chan %04x chsa %04x spad %08x INTS[%02x] %08x\n", chan, rchsa, t, ix, INTS[ix]); + if ((TRAPME = checkxio(rchsa, &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 */ +#ifdef TEST + { + DIB *dibp = dib_chan[chan]; /* get channel dib pointer */ + if (dibp != 0) { + CHANP *chp = dibp->chan_prg; /* get channel prog pointer */ + if ((chp != 0) && post_csw(chp, 0)) { + sim_debug(DEBUG_XIO, &cpu_dev, + "DCI After checkxio call removed FIFO entry chp %p\n", chp); + } + } + } +#endif /* SPAD entries for interrupts begin at 0x80 */ INTS[ix] &= ~INTS_ENAB; /* disable specified int level */ SPAD[ix+0x80] &= ~SINT_ENAB; /* disable in SPAD too */ @@ -6889,6 +6894,7 @@ mcheck: sim_debug(DEBUG_XIO, &cpu_dev, "XIO ACI chan %04x chsa %04x spad %08x INTS[%02x] %08x\n", chan, rchsa, t, ix, INTS[ix]); + if ((TRAPME = checkxio(rchsa, &rstatus))) goto newpsd; /* error returned, trap cpu */ /* SPAD entries for interrupts begin at 0x80 */ @@ -6904,18 +6910,21 @@ mcheck: sim_debug(DEBUG_XIO, &cpu_dev, "XIO DACI chan %04x chsa %04x spad %08x INTS[%02x] %08x BLK %1x\n", chan, rchsa, t, ix, INTS[ix], CPUSTATUS&0x80?1:0); + if ((TRAPME = checkxio(rchsa, &rstatus))) goto newpsd; /* error returned, trap cpu */ + sim_debug(DEBUG_XIO, &cpu_dev, + "DACI after checkxio chan %04x suba %04x status %08x\n", 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 */ #ifndef NOTNOW - sim_debug(DEBUG_IRQ, &cpu_dev, + sim_debug(DEBUG_XIO, &cpu_dev, "DACI INTS[%02x] %08x Skipinstr %1x set PSD1 %08x PSD2 %08x CPUSTATUS %08x\n", ix, INTS[ix], skipinstr, PSD1, PSD2, CPUSTATUS); #endif - skipinstr = 1; /* skip interrupt test */ /*XXX*/ drop_nop = 0; /* nothing to drop */ PSD1 = ((PSD1 & 0x87fffffe) | (rstatus & 0x78000000)); /* insert status */ break; diff --git a/SEL32/sel32_defs.h b/SEL32/sel32_defs.h index 9316066..36050f1 100644 --- a/SEL32/sel32_defs.h +++ b/SEL32/sel32_defs.h @@ -93,12 +93,11 @@ #define FLAG_PCI 0x0800 /* Program controlled interrupt */ #define FLAG_RTO 0x0400 /* Real-Time Option */ -#define BUFF_EMPTY 0x4 /* Buffer is empty */ -#define BUFF_DIRTY 0x8 /* Buffer is dirty flag */ -#define BUFF_NEWCMD 0x10 /* Channel ready for new command */ -#define BUFF_CHNEND 0x20 /* Channel end */ -#define BUFF_DONE 0x40 /* Channel program done */ -#define BUFF_NEXT 0x80 /* Continue Channel with next IOCB */ +#define BUFF_EMPTY 0x0 /* Buffer is empty */ +#define BUFF_BUSY 0x4 /* Channel program busy & empty */ +#define BUFF_NEXT 0xC /* 0x08|0x04 Continue Channel with next IOCB */ +#define BUFF_CHNEND 0x14 /* 0x10|0x04 Channel end */ +#define BUFF_DONE 0x20 /* 0x20 Channel ready for new command */ #define MAX_CHAN 128 /* max channels that can be defined */ #define SUB_CHANS 256 /* max sub channels that can be defined */ @@ -203,7 +202,7 @@ typedef struct chp { uint16 chan_status; /* Channel status */ uint16 chan_dev; /* Device on channel */ uint8 ccw_cmd; /* Channel command and flags */ - uint8 chan_byte; /* Current byte, dirty/full */ + uint8 chan_byte; /* Current byte, empty/full */ uint8 chan_int; /* channel interrupt level */ } CHANP; diff --git a/SEL32/sel32_disk.c b/SEL32/sel32_disk.c index 7b70dd4..d74f39e 100644 --- a/SEL32/sel32_disk.c +++ b/SEL32/sel32_disk.c @@ -741,7 +741,8 @@ t_stat disk_srv(UNIT *uptr) chan_write_byte(chsa, &ch); /* bytes 8-11 - drive mode register entries from assigned disk */ - ch = disk_type[type].type & 0xff; /* type byte */ +//051520 ch = disk_type[type].type & 0xff; /* type byte */ + ch = disk_type[type].type & 0xfc; /* zero bits 6 & 7 in type byte */ sim_debug(DEBUG_DETAIL, dptr, "disk_srv datr unit=%02x 1 %02x\n", unit, ch); chan_write_byte(chsa, &ch); @@ -1332,7 +1333,8 @@ t_stat disk_srv(UNIT *uptr) /* and byte 28 is number of heads. Byte 26 is mode. */ /* Byte 25 is copy of byte 27. */ buf[25] = disk_type[type].spt & 0xff; - buf[26] = disk_type[type].type; /* mode data in UDP/DPII */ +//051520 buf[26] = disk_type[type].type & 0xff; /* mode data in UDP/DPII */ + buf[26] = disk_type[type].type & 0xfc; /* zero bits 6 & 7 in type byte */ buf[27] = disk_type[type].spt & 0xff; buf[28] = disk_type[type].nhds & 0xff; diff --git a/SEL32/sel32_fltpt.c b/SEL32/sel32_fltpt.c index 189fbb0..1a8db2d 100644 --- a/SEL32/sel32_fltpt.c +++ b/SEL32/sel32_fltpt.c @@ -73,6 +73,9 @@ t_uint64 s_mpfd(t_uint64 reg, t_uint64 mem, uint32 *cc); t_uint64 s_dvfd(t_uint64 reg, t_uint64 mem, uint32 *cc); uint32 s_normfw(uint32 mem, uint32 *cc); t_uint64 s_normfd(t_uint64 mem, uint32 *cc); +uint32 o_adfw(uint32 reg, uint32 mem, uint32 *cc); +t_uint64 o_adfd(t_uint64 reg, t_uint64 mem, uint32 *cc); +t_uint64 n_adfd(t_uint64 reg, t_uint64 mem, uint32 *cc, uint32 type); #define NORMASK 0xf8000000 /* normalize 5 bit mask */ #define DNORMASK 0xf800000000000000ll /* double normalize 5 bit mask */ @@ -82,6 +85,13 @@ t_uint64 s_normfd(t_uint64 mem, uint32 *cc); #define DFSVAL 0xff00000000000000ll /* minus full scale value */ #define DFRMASK 0x80ffffffffffffffll /* fraction mask */ #define NEGATE32(val) ((~val) + 1) /* negate a value 16/32/64 bits */ +#define MEMNEG 1 /* mem arg is negative */ +#define REGNEG 2 /* reg arg is negative */ +#define RESNEG 4 /* result is negative */ + +#define USE_ORIG +//#define USE_NEW +//#define USE_DIAG /* normalize floating point fraction */ uint32 s_nor(uint32 reg, uint32 *exp) { @@ -140,11 +150,18 @@ t_uint64 s_nord(t_uint64 reg, uint32 *exp) { * two's complement double precision fraction is returned in * * (r6,r7). * ***************************************************************/ +/* type of operation action flags */ +#define FPWDV 0x0001 /* floating point word operation */ +#define FPADD 0x0002 /* floating point add */ + struct fpnum { - int32 msw; /* most significent word */ - int32 lsw; /* least significient word */ - int32 exp; /* exponent */ - int32 CCs; /* condition codes */ + t_uint64 num; /* 64 bit number */ + int32 msw; /* most significent word */ + int32 lsw; /* least significient word */ + int32 exp; /* exponent */ + int32 CCs; /* condition codes */ + uint8 sign; /* original sign */ + uint8 flags; /* action flags for number */ }; /* unpack single precision floating point number */ @@ -158,7 +175,7 @@ void unpacks(struct fpnum *np) { if (ex & 0x80000000) /* check for negative */ ex ^= 0xff000000; /* reset sign & complement exponent */ np->msw ^= ex; /* replace exponent with sign extension */ - ex = ((uint32)ex) >> 24; /* right justify the exponent */ + ex = ((uint32)ex) >> 24; /* srl 24 right justify the exponent */ ex -= 0x40; /* unbias exponent */ np->exp = ex; /* save the exponent */ np->CCs = 0; /* zero CCs for later */ @@ -173,7 +190,7 @@ void unpackd(struct fpnum *np) { if (ex & 0x80000000) /* check for negative */ ex ^= 0xff000000; /* reset sign & complement exponent */ np->msw ^= ex; /* replace exponent with sign extension */ - ex = ((uint32)ex) >> 24; /* right justify the exponent */ + ex = ((uint32)ex) >> 24; /* srl 24 right justify the exponent */ ex -= 0x40; /* unbias exponent */ np->exp = ex; /* save exponent */ np->CCs = 0; /* zero CCs for later */ @@ -208,28 +225,24 @@ void unpackd(struct fpnum *np) { * 1 1 0 1 exp overflow, fraction positive * * * **************************************************************/ -/** Normalization and rounding of single precision number */ +/* Normalization and rounding of single precision number */ void packs(struct fpnum *np) { uint32 ex, tmp, tmp2; - t_uint64 num = ((t_uint64)np->msw << 32) | np->lsw; /* make 64 bit num */ - + t_uint64 num = ((t_uint64)np->msw << 32) | (uint32)np->lsw; /* make 64 bit num */ sim_debug(DEBUG_EXP, &cpu_dev, "pack entry msw %08x lsw %08x exp %08x num %016llx\n", np->msw, np->lsw, np->exp, num); num = ((t_int64)num) << 3; /* slad 3 to align for normalization */ - sim_debug(DEBUG_EXP, &cpu_dev, - "pack pl 0 num %016llx ex %08x exp %08x\n", num, ex, np->exp); + "pack pl 0 num %016llx exp %08x\n", num, np->exp); num = s_nord(num, &ex); /* normalize the number with cnt in ex */ - sim_debug(DEBUG_EXP, &cpu_dev, "pack pl 1 num %016llx ex %08x exp %08x\n", num, ex, np->exp); num = ((t_int64)num) >> 7; /* srad 7 to align & sign extend number */ - sim_debug(DEBUG_EXP, &cpu_dev, "pack pl 2 num %016llx ex %08x exp %08x\n", num, ex, np->exp); @@ -259,11 +272,7 @@ void packs(struct fpnum *np) { sim_debug(DEBUG_EXP, &cpu_dev, "pack pl 4 num %016llx msw %08x exp %08x ex %08x\n", num, np->msw, np->exp, ex); -//4110000 bad if ((t_int64)num <= DFSVAL) { /* see if > 0xff00000000000000 */ -//4110000 bad if ((t_int64)num == DFSVAL) { /* see if > 0xff00000000000000 */ -//80000001 has cc bad if ((t_int64)num >= DFSVAL) { /* see if > 0xff00000000000000 */ -//needs >= for BEF -> BEF is EQ to DFSVAL - if (((t_int64)num) >= DFSVAL) { /* see if > 0xff00000000000000 */ + if (((t_int64)num) == DFSVAL) { /* see if > 0xff00000000000000 */ /* fixup fraction to not have -1 in results */ num = ((t_int64)num) >> 4; /* sra 4 shift over 4 bits */ ex += 1; /* bump exponent */ @@ -278,6 +287,7 @@ void packs(struct fpnum *np) { "pack n&r num %016llx msw %08x exp %08x ex %08x\n", num, np->msw, np->exp, ex); if (((int32)(np->exp)) < 0) { /* check for exp neg underflow */ np->CCs |= CC1BIT; /* set CC1 & return zero */ + np->num = 0; np->msw = 0; np->lsw = 0; return; @@ -340,8 +350,7 @@ void packd(struct fpnum *np) { else np->CCs = CC2BIT; /* show fraction positive */ -// if ((t_int64)num <= DFSVAL) { /* see if > 0xff00000000000000 */ - if ((t_int64)num >= DFSVAL) { /* see if > 0xff00000000000000 */ + if ((t_int64)num == DFSVAL) { /* see if > 0xff00000000000000 */ num >>= 4; /* shift over 4 bits */ ex += 1; /* bump exponent */ } @@ -350,9 +359,10 @@ void packd(struct fpnum *np) { np->exp += 1; /* correct shift count */ if (((int32)(np->exp)) < 0) { /* check for exp neg underflow */ np->CCs |= CC1BIT; /* set CC1 & return zero */ + np->num = 0; np->msw = 0; np->lsw = 0; - return; + return; } /* if no exponent overflow merge exp & fraction & return */ if (((int32)(np->exp)) <= 0x7f) { @@ -387,10 +397,74 @@ uint32 s_normfw(uint32 mem, uint32 *cc) { } sim_debug(DEBUG_EXP, &cpu_dev, "NORMFW entry mem %08x\n", mem); +#ifndef OLDWAY fpn.msw = mem; /* save upper 32 bits */ fpn.lsw = 0; /* clear lower 32 bits */ unpacks(&fpn); /* unpack number */ packs(&fpn); /* pack it back up */ +#else + fpn.sign = 0; + + /* special case 0x80000000 (-0) to set CCs to 1011 * value to 0x80000001 */ + if (mem == 0x80000000) { + fpn.CCs = CC1BIT|CC3BIT|CC4BIT; /* we have AE, exp overflow, neg frac */ + fpn.msw = 0x80000001; /* return max neg value */ + goto goret; /* return */ + } + + /* special case pos exponent & zero mantissa to be 0 */ + if (((mem & 0x80000000) == 0) && ((mem & 0xff000000) > 0) && ((mem & 0x00ffffff) == 0)) { + fpn.msw = 0; /* 0 to any power is still 0 */ + fpn.CCs = CC4BIT; /* set zero CC */ + goto goret; /* return */ + } + + /* if we have 1xxx xxxx 0000 0000 0000 0000 0000 0000 */ + /* we need to convert to 1yyy yyyy 1111 0000 0000 0000 0000 0000 */ + /* where y = x - 1 */ + if ((mem & 0x80ffffff) == 0x80000000) { + int nexp = (0x7f000000 & mem) - 0x01000000; + mem = 0x80000000 | (nexp & 0x7f000000) | 0x00f00000; + } + + fpn.exp = (mem & 0x7f000000) >> 24; /* get exponent */ + if (mem & 0x80000000) { /* test for neg */ + fpn.sign = MEMNEG; /* we are neq */ + mem = NEGATE32(mem); /* two's complement */ + fpn.exp ^= 0x7f; /* complement exponent */ + } + fpn.msw = mem & 0x00ffffff; /* get mantissa */ + + /* now make sure number is normalized */ + if (fpn.msw != 0) { + while ((fpn.msw & 0x00f00000) == 0) { + fpn.msw <<= 4; /* move up a nibble */ + fpn.exp--; /* and decrease exponent */ + } + } + if (fpn.exp < 0) { + fpn.CCs = CC1BIT; /* we have underflow */ + if (fpn.sign & MEMNEG) /* we are neg (1) */ + fpn.CCs |= CC3BIT; /* set neg CC */ + else + fpn.CCs |= CC2BIT; /* set pos CC */ + fpn.msw = 0; /* number too small, make 0 */ + fpn.exp = 0; /* exponent too */ + goto goret; /* return */ + } + + /* rebuild normalized number */ + fpn.msw = ((fpn.msw & 0x00ffffff) | ((fpn.exp & 0x7f) << 24)); + if (fpn.sign & MEMNEG) /* we are neg (1) */ + fpn.msw = NEGATE32(fpn.msw); /* two's complement */ + if (fpn.msw == 0) + fpn.CCs = CC4BIT; /* show zero */ + else if (fpn.msw & 0x80000000) /* neqative? */ + fpn.CCs = CC3BIT; /* show negative */ + else + fpn.CCs = CC2BIT; /* show positive */ +goret: +#endif ret = fpn.msw; /* return normalized number */ sim_debug(DEBUG_EXP, &cpu_dev, "NORMFW return mem %08x result %08x CC's %08x\n", mem, ret, fpn.CCs); @@ -402,9 +476,50 @@ uint32 s_normfw(uint32 mem, uint32 *cc) { /* add memory floating point number to register floating point number */ /* set CC1 if overflow/underflow */ uint32 s_adfw(uint32 reg, uint32 mem, uint32 *cc) { + uint32 retval, CC; + +#ifdef USE_ORIG +// printf("s_adfw entry reg %08x mem %08x\n", reg, mem); + + /* do original SEL floating add */ + retval = o_adfw(reg, mem, &CC); /* get 32 bit value */ +// printf("s_adfw exit result %08x CC's %08x\n", retval, CC); + *cc = CC; /* return the CC's */ + return retval; /* we are done */ +#endif + +#ifndef USE_ORIG + u_int64_t dst, src, ret; + int32 type = (FPWDV | FPADD); /* do single precision add */ + +// printf("s_adfw entry reg %08x mem %08x\n", reg, mem); + dst = ((u_int64_t)reg) << 32; /* make 64 bit value */ + src = ((u_int64_t)mem) << 32; /* make 64 bit value */ + +#ifdef USE_DIAG + /* do diagnostic floating add */ + ret = d_adsu(dst, src, &CC, type); +#endif + +#ifdef USE_NEW + /* do new floating add */ + ret = n_adfd(dst, src, &CC, type); +#endif + + retval = (ret >> 32) & 0xffffffff; /* 32 bits */ +// printf("s_adfw exit ret %016lx result %08x CC's %08x\n", ret, retval, CC); + *cc = CC; /* return the CC's */ + return retval; /* we are done */ +#endif /* USE_ORIG */ +} + +#ifdef USE_ORIG +/* add memory floating point number to register floating point number */ +/* set CC1 if overflow/underflow */ +uint32 o_adfw(uint32 reg, uint32 mem, uint32 *cc) { uint32 mfrac, rfrac, frac, ret=0, oexp; uint32 CC, sc, sign, expr, expm, exp; -#ifdef DO_NORMALIZE +#ifndef DO_NORMALIZE struct fpnum fpn = {0}; #endif @@ -412,12 +527,11 @@ uint32 s_adfw(uint32 reg, uint32 mem, uint32 *cc) { CC = 0; /* clear local CC's */ sim_debug(DEBUG_EXP, &cpu_dev, -// "ADFW entry mem %08x reg %08x result %08x\n", mem, reg, ret); "ADFW entry mem %08x reg %08x\n", mem, reg); /* process the memory operand value */ if (mem == 0) { /* test for zero operand */ ret = reg; /* return original register value */ -#ifdef DO_NORMALIZE +#ifndef DO_NORMALIZE if (ret == 0) goto goout; /* nothing + nothing = nothing */ fpn.msw = ret; /* save upper 32 bits */ @@ -427,10 +541,17 @@ uint32 s_adfw(uint32 reg, uint32 mem, uint32 *cc) { ret = fpn.msw; /* return normalized number */ CC = fpn.CCs; /* set the cc's */ goto goout2; /* go set cc's and return */ +#else + ret = s_normfw(reg, &CC); /* normalize the reg */ + if (CC & CC1BIT) /* if AE, just exit */ + goto goout2; #endif goto goout; /* go set cc's and return */ } + +//#define EXMASK 0x7f000000 /* exponent mask */ expm = mem & EXMASK; /* extract exponent from operand */ +//#define FRMASK 0x80ffffff /* fraction mask */ mfrac = mem & FRMASK; /* extract fraction */ if (mfrac & MSIGN) { /* test for negative fraction */ /* negative fraction */ @@ -442,7 +563,7 @@ uint32 s_adfw(uint32 reg, uint32 mem, uint32 *cc) { /* process the register operator value */ if (reg == 0) { ret = mem; /* return original mem operand value */ -#ifdef DO_NORMALIZE +#ifndef DO_NORMALIZE if (ret == 0) goto goout; /* nothing + nothing = nothing */ /* reg is 0 and mem is not zero, normalize mem */ @@ -453,10 +574,18 @@ uint32 s_adfw(uint32 reg, uint32 mem, uint32 *cc) { ret = fpn.msw; /* return normalized number */ CC = fpn.CCs; /* set the cc's */ goto goout2; /* go set cc's and return */ +#else + ret = s_normfw(mem, &CC); /* normalize the mem */ + if (CC & CC1BIT) /* if AE, just exit */ + goto goout2; #endif goto goout; /* go set cc's and return */ } + CC = 0; /* clear local CC's */ + +//#define EXMASK 0x7f000000 /* exponent mask */ expr = reg & EXMASK; /* extract exponent from reg operand */ +//#define FRMASK 0x80ffffff /* fraction mask */ rfrac = reg & FRMASK; /* extract fraction */ if (rfrac & MSIGN) { /* test for negative fraction */ /* negative fraction */ @@ -478,8 +607,7 @@ uint32 s_adfw(uint32 reg, uint32 mem, uint32 *cc) { /* difference is <= 6, so adjust to smaller value for add */ /* difference is number of 4 bit right shifts to do */ /* (exp >> 24) * 4 */ -//42220 sc = exp >> (24 - 2); /* shift count down to do x4 the count */ -/*try*/ sc = (exp >> 24) * 4; /* shift count down to do x4 the count */ + sc = (uint32)exp >> (24 - 2); /* shift count down to do x4 the count */ rfrac = ((int32)rfrac) >> sc; oexp = expm; /* mem is larger exponent, save for final exponent add */ } else { @@ -493,9 +621,8 @@ uint32 s_adfw(uint32 reg, uint32 mem, uint32 *cc) { /* difference is <= 6, so adjust to smaller value for add */ /* difference is number of 4 bit right shifts to do */ /* (exp >> 24) * 4 */ -//42220 sc = exp >> (24 - 2); /* shift count down to do x4 the count */ -/*try*/ sc = (exp >> 24) * 4; /* shift count down to do x4 the count */ - frac = ((int32)mfrac) >> sc; + sc = (uint32)exp >> (24 - 2); /* shift count down to do x4 the count */ + mfrac = ((int32)mfrac) >> sc; oexp = expr; /* reg is larger exponent, save for final exponent add */ } sim_debug(DEBUG_EXP, &cpu_dev, @@ -510,7 +637,7 @@ uint32 s_adfw(uint32 reg, uint32 mem, uint32 *cc) { } if ((int32)frac >= 0x10000000) { /* check for overflow */ /* overflow */ - frac = (int32)frac >> 1; /* sra 1 */ + frac = ((int32)frac) >> 1; /* sra 1 */ } else { /* no overflow */ /* check for underflow */ @@ -519,11 +646,11 @@ uint32 s_adfw(uint32 reg, uint32 mem, uint32 *cc) { oexp -= 0x01000000; /* adjust exponent */ } else { /* no underflow */ - frac = (int32)frac >> 1; /* sra 1 */ + frac = ((int32)frac) >> 1; /* sra 1 */ } } /* normalize the frac value and put exponent into exp */ - frac = s_nor(frac, &exp); + frac = s_nor(frac, (int32 *)&exp); if (frac == MSIGN) { /* check for minus zero */ frac = NORMASK; /* load correct value */ exp += 1; /* adjust the exponent too */ @@ -540,7 +667,7 @@ uint32 s_adfw(uint32 reg, uint32 mem, uint32 *cc) { goto goout; /* go set cc's and return */ } } - exp = exp << 24; /* put exponent in upper byte */ + exp = (uint32)exp << 24; /* put exponent in upper byte */ exp -= 0x3f000000; /* adjust the shift count */ /* rounding complete, compute final exponent */ /* must check for exponent over/underflow */ @@ -568,6 +695,7 @@ ARUNFLO: CC |= CC3BIT; /* set neg fraction bit CC3 */ } *cc = CC; /* return CC's */ +#ifdef NOTUSED /* return value is not valid, but return fixup value anyway */ switch ((CC >> 27) & 3) { /* rt justify CC3 & CC4 */ case 0x0: @@ -583,19 +711,22 @@ ARUNFLO: return 0x80000001; /* negative overflow */ break; } +#endif /* never here */ goto goout2; /* go set cc's and return */ } /* no over/underflow */ frac = (int32)frac >> 7; /* positive fraction sra r7,7 */ +//#define FRMASK 0x80ffffff /* fraction mask */ frac &= FRMASK; /* mask out the exponent field */ if ((int32)frac > 0) { /* see if positive */ ret = exp | frac; /* combine exponent & fraction */ } else { if (frac != 0) { +//#define EXMASK 0x7f000000 /* exponent mask */ exp ^= EXMASK; /* for neg fraction, complement exponent */ - ret = exp | frac; /* combine exponent & fraction */ } + ret = exp | frac; /* combine exponent & fraction */ } /* come here to set cc's and return */ /* ret has return value */ @@ -613,6 +744,7 @@ goout2: *cc = CC; /* return CC's */ return ret; /* return result */ } +#endif /* subtract memory floating point number from register floating point number */ uint32 s_sufw(uint32 reg, uint32 mem, uint32 *cc) { @@ -628,11 +760,79 @@ t_uint64 s_normfd(t_uint64 mem, uint32 *cc) { *cc = CC4BIT; /* set the cc's */ return 0; /* return zero */ } + sim_debug(DEBUG_EXP, &cpu_dev, + "NORMFD entry mem %016llx\n", mem); +#ifndef OLDWAY fpn.msw = (mem >> 32); /* get msw */ fpn.lsw = mem & 0xffffffff; /* get lsw */ unpackd(&fpn); /* unpack number */ packd(&fpn); /* pack it back up */ ret = ((t_uint64)fpn.msw << 32) | fpn.lsw; /* make 64 bit num */ +#else + fpn.sign = 0; + + /* special case 0x8000000000000000 (-0) to set CCs to 1011 */ + /* and value to 0x8000000000000001 */ +//#define DMSIGN 0x8000000000000000LL /* 64 bit minus sign */ + if (mem == 0x8000000000000000LL) { + fpn.CCs = CC1BIT|CC3BIT|CC4BIT; /* we have AE, exp overflow, neg frac */ + ret = 0x8000000000000001LL; /* return max neg value */ + goto goret; /* return */ + } + + /* special case pos exponent & zero mantissa to be 0 */ + if (((mem & 0x8000000000000000LL) == 0) && ((mem & 0xff00000000000000LL) > 0) && + (mem & 0x00ffffffffffffffLL) == 0)) { + ret = 0; /* 0 to any power is still 0 */ + fpn.CCs = CC4BIT; /* set zero CC */ + goto goret; /* return */ + } + + /* if we have 1xxx xxxx 0000 0000 0000 0000 0000 0000 */ + /* we need to convert to 1yyy yyyy 1111 0000 0000 0000 0000 0000 */ + /* where y = x - 1 */ + if ((mem & 0x80ffffffffffffffLL) == 0x8000000000000000LL) { + t_uint64 nexp = (0x7f00000000000000LL & mem) - 0x0100000000000000LL; + mem = 0x8000000000000000LL | (nexp & 0x7f00000000000000LL) | 0x00f0000000000000LL; + } + +//#define DEXMASK 0x7f00000000000000ll /* exponent mask */ + fpn.exp = (mem & 0x7f00000000000000LL) >> 56; /* get exponent */ + if (mem & 0x8000000000000000LL) { /* test for neg */ + fpn.sign = MEMNEG; /* we are neq */ + mem = NEGATE32(mem); /* two's complement */ + fpn.exp ^= 0x7f; /* complement exponent */ + } + fpn.num = mem & 0x00ffffffffffffffLL; /* get mantissa */ + + /* now make sure number is normalized */ + while ((fpn.num != 0) && ((fpn.num & 0x00f0000000000000LL) == 0)) { + fpn.num <<= 4; /* move up a nibble */ + fpn.exp--; /* and decrease exponent */ + } + if (fpn.exp < 0) { + fpn.CCs = CC1BIT; /* we have underflow */ + if (fpn.sign & MEMNEG) /* we are neg (1) */ + fpn.CCs |= CC3BIT; /* set neg CC */ + else + fpn.CCs |= CC2BIT; /* set pos CC */ + ret = 0; /* number too small, make 0 */ + goto goret; /* return */ + } + + /* rebuild normalized number */ + ret = ((fpn.num & 0x00ffffffffffffff) | (((t_uint64)fpn.exp & 0x7f) << 56)); + if (fpn.sign & MEMNEG) /* we were neg (1) */ + ret = NEGATE32(ret); /* two's complement */ + if (ret == 0) + fpn.CCs = CC4BIT; /* show zero */ + else if (ret & 0x8000000000000000LL) /* neqative? */ + fpn.CCs = CC3BIT; /* show negative */ + else + fpn.CCs = CC2BIT; /* show positive */ +goret: +#endif +// ret = ((t_uint64)fpn.msw << 32) | fpn.lsw; /* make 64 bit num */ sim_debug(DEBUG_EXP, &cpu_dev, "NORMFD return mem %016llx result %016llx CC's %08x\n", mem, ret, fpn.CCs); /* return normalized number */ @@ -641,50 +841,138 @@ t_uint64 s_normfd(t_uint64 mem, uint32 *cc) { } /* add memory floating point number to register floating point number */ +/* do double precision add */ /* set CC1 if overflow/underflow */ t_uint64 s_adfd(t_uint64 reg, t_uint64 mem, uint32 *cc) { - t_uint64 temp, dblmem, dblreg, ret; +#ifdef USE_ORIG + t_uint64 retval; + uint32 CC; +// printf("s_adfd entry reg %016lx mem %016lx\n", reg, mem); + + /* do original SEL floating add */ + retval = o_adfd(reg, mem, &CC); /* get 32 bit value */ +// printf("s_adfd exit result %016lx CC's %08x\n", retval, CC); + *cc = CC; /* return the CC's */ + return retval; /* we are done */ +#endif + +#ifndef USE_ORIG + u_int64_t dst = reg, src = mem, retval; + int32 type = (FPADD); /* do double precision add */ + uint32 CC; + +// printf("s_adfd entry reg %016lx mem %016lx\n", reg, mem); + +#ifdef USE_DIAG + /* do diagnostic floating double add */ + retval = d_adsu(dst, src, &CC, type); +#endif + +#ifdef USE_NEW + /* do new floating add */ + retval = n_adfd(dst, src, &CC, type); +#endif + +// printf("s_adfd exit result %016lx CC's %08x\n", retval, CC); + *cc = CC; /* return the CC's */ + return retval; /* we are done */ +#endif /* USE_ORIG */ +} + +#ifdef USE_ORIG +/* add memory floating point number to register floating point number */ +/* set CC1 if overflow/underflow */ +t_uint64 o_adfd(t_uint64 reg, t_uint64 mem, uint32 *cc) { + t_uint64 dfrac, dblmem, dblreg, ret; uint32 CC, sc, sign, expm, expr, exp; +#ifndef DO_NORMALIZE + struct fpnum fpn = {0}; +#endif *cc = 0; /* clear the CC'ss */ CC = 0; /* clear local CC's */ -#ifndef DO_NORMALIZE + sim_debug(DEBUG_EXP, &cpu_dev, + "ADFD entry mem %016llx reg %016llx\n", mem, reg); /* process the memory operand value */ if (mem == 0) { /* test for zero operand */ ret = reg; /* return original reg value */ +#ifndef DO_NORMALIZE + if (ret == 0) + goto goout; /* nothing + nothing = nothing */ + /* reg is 0 and mem is not zero, normalize mem */ + fpn.msw = (reg >> 32) & 0xffffffff; /* get msw */ + fpn.lsw = reg & 0xffffffff; /* get lsw */ + unpackd(&fpn); /* unpack number */ + packd(&fpn); /* pack it back up */ + ret = ((t_uint64)fpn.msw << 32) | fpn.lsw; /* make 64 bit num */ + CC = fpn.CCs; /* set the cc's */ + goto goout2; +#else + ret = s_normfd(reg, &CC); /* normalize the reg */ + if (CC & CC1BIT) /* if AE, just exit */ + goto goout2; +#endif goto goout; /* go set cc's and return */ } -#endif +//? mem = s_normfd(mem, &CC); /* normalize the mem */ + /* separate mem dw into two 32 bit numbers */ /* mem value is not zero, so extract exponent and mantissa */ +//#define DEXMASK 0x7f00000000000000LL /* double exponent mask */ expm = (uint32)((mem & DEXMASK) >> 32); /* extract exponent */ +//#define DFRMASK 0x80ffffffffffffffll /* fraction mask */ dblmem = mem & DFRMASK; /* extract fraction */ if (dblmem & DMSIGN) { /* test for negative fraction */ /* negative fraction */ +//#define EXMASK 0x7f000000 /* exponent mask */ expm ^= EXMASK; /* ones complement the exponent */ +//#define DEXMASK 0x7f00000000000000LL /* double exponent mask */ dblmem |= DEXMASK; /* adjust the fraction */ } -#ifndef DO_NORMALIZE /* process the register operator value */ if (reg == 0) { /* see if reg value is zero */ ret = mem; /* return original mem operand value */ +#ifndef DO_NORMALIZE + if (ret == 0) + goto goout; /* nothing + nothing = nothing */ + /* reg is 0 and mem is not zero, normalize mem */ + fpn.msw = (mem >> 32); /* get msw */ + fpn.lsw = mem & 0xffffffff; /* get lsw */ + unpackd(&fpn); /* unpack number */ + packd(&fpn); /* pack it back up */ + ret = ((t_uint64)fpn.msw << 32) | fpn.lsw; /* make 64 bit num */ + CC = fpn.CCs; /* set the cc's */ + goto goout2; +#else + ret = s_normfd(mem, &CC); /* normalize the mem */ + if (CC & CC1BIT) /* if AE, just exit */ + goto goout2; +#endif goto goout; /* go set cc's and return */ } -#endif +//? reg = s_normfd(reg, &CC); /* normalize the reg */ + CC = 0; /* clear local CC's */ + /* separate reg dw into two 32 bit numbers */ /* reg value is not zero, so extract exponent and mantissa */ +//#define DEXMASK 0x7f00000000000000LL /* double exponent mask */ expr = (uint32)((reg & DEXMASK) >> 32); /* extract exponent */ +//#define DFRMASK 0x80ffffffffffffffll /* fraction mask */ dblreg = reg & DFRMASK; /* extract fraction */ if (dblreg & DMSIGN) { /* test for negative fraction */ /* negative fraction */ +//#define EXMASK 0x7f000000 /* exponent mask */ expr ^= EXMASK; /* ones complement the exponent */ +//#define DEXMASK 0x7f00000000000000LL /* double exponent mask */ dblreg |= DEXMASK; /* adjust the fraction */ } exp = expr - expm; /* subtract memory exp from reg exp */ - sign = expr; /* save register exponent */ + sim_debug(DEBUG_EXP, &cpu_dev, + "ADFD2 exp calc expr %04x expm %04x exp %04x\n", expr, expm, exp); + sign = expr; /* save register exponent */ if (exp & MSIGN) { /* exponent difference is negative */ exp = NEGATE32(exp); /* make exponent difference positive */ @@ -695,8 +983,8 @@ t_uint64 s_adfd(t_uint64 reg, t_uint64 mem, uint32 *cc) { } /* difference is <= 13, so adjust to smaller value for add */ /* difference is number of 4 bit right shifts to do */ - /* (exp >> 24) *4 */ - sc = exp >> (24 - 2); /* shift count down to do x4 the count */ + /* (exp >> 24) * 4 */ + sc = (uint32)exp >> (24 - 2); /* shift count down to do x4 the count */ dblreg = (t_int64)dblreg >> sc; /* shift sra r4,cnt x4 */ sign = expm; /* mem is larger exponent, so save it */ } @@ -710,22 +998,30 @@ t_uint64 s_adfd(t_uint64 reg, t_uint64 mem, uint32 *cc) { goto goout; /* go set cc's and return */ } /* diff is <= 13, normalize */ - sc = exp >> (24 - 2); /* shift count down to do x4 the count */ + /* (exp >> 24) * 4 */ + sc = (uint32)exp >> (24 - 2); /* shift count down to do x4 the count */ dblmem = (t_int64)dblmem >> sc; /* shift sra r6,cnt x4 */ + sign = expr; /* reg is larger exponent, so save it */ } - temp = dblreg + dblmem; /* add operand to operator (fractions) */ - if (temp == 0) { + sim_debug(DEBUG_EXP, &cpu_dev, + "ADFD3 after exp calc exp %04x sc %04x sign %04x\n", exp, sc, sign); + dfrac = dblreg + dblmem; /* add operand to operator (fractions) */ + sim_debug(DEBUG_EXP, &cpu_dev, + "ADFD4 frac calc dbkreg %014llx dblmem %014llx dfrac %014llx\n", + dblreg, dblmem, dfrac); + if (dfrac == 0) { /* return the zero value */ - ret = temp; /* return zero to caller */ + ret = dfrac; /* return zero to caller */ goto goout; /* go set cc's and return */ } - exp = sign - 0x3f000000; /* adjust exponent */ - temp = (t_int64)temp << 3; /* adjust the mantissa sla 3 */ - /* normalize the value in temp and put exponent into sc */ - temp = s_nord(temp, &sc); - if (temp == DMSIGN) { + exp = (int32)sign - 0x3f000000; /* adjust exponent */ + dfrac = (t_int64)dfrac << 3; /* adjust the mantissa sla 3 */ + + /* normalize the value in dfrac and put exponent into sc */ + dfrac = s_nord(dfrac, &sc); + if (dfrac == DMSIGN) { /* value is neg zero, so fix it up */ - temp = DNORMASK; /* correct the value */ + dfrac = DNORMASK; /* correct the value */ sc++; /* adjust exponent too */ } sc = (sc & 0xff) << 24; /* put nord exp in upper byte */ @@ -743,21 +1039,19 @@ t_uint64 s_adfd(t_uint64 reg, t_uint64 mem, uint32 *cc) { /* We have exponent underflow if result negative */ goto DUNFLO; /* branch on underflow. */ - ret = (t_int64)temp >> 7; /* position fraction srad 7 */ + ret = (t_int64)dfrac >> 7; /* position fraction srad 7 */ +//#define DFRMASK 0x80ffffffffffffffll /* fraction mask */ ret &= DFRMASK; /* mask out exponent field leaving fraction */ /* test sign of fraction */ if (ret != 0) { /* test for zero, to return zero */ - if (ret & DMSIGN) { /* see if negative */ + if (ret & DMSIGN) /* see if negative */ /* fraction is negative */ exp ^= EXMASK; /* neg fraction, so complement exponent */ - ret = ret | ((t_uint64)exp << 32); /* position and insert exponent */ - } -/*NEW*/ else -/*NEW*/ ret = ret | ((t_uint64)exp << 32); /* position and insert exponent */ + ret = ret | ((t_uint64)exp << 32); /* position and insert exponent */ } /* come here to set cc's and return */ - /* temp has return value */ + /* dfrac has return value */ goout: if (ret & DMSIGN) CC |= CC3BIT; /* CC3 for neg */ @@ -767,22 +1061,42 @@ goout: else CC |= CC2BIT; /* CC2 for greater than zero */ goout2: - /* return temp to destination reg */ + sim_debug(DEBUG_EXP, &cpu_dev, + "ADFD return mem %016llx reg %016llx result %016llx CC %08x\n", mem, reg, ret, CC); + /* return dfrac to destination reg */ +#ifdef NOT_VALID + /* return value is not valid, but return fixup value anyway */ + switch ((CC >> 27) & 3) { /* rt justify CC3 & CC4 */ + case 0x0: + ret = 0; /* pos underflow */ + break; + case 0x1: + ret = 0x7fffffffffffffffLL; /* positive overflow */ + break; + case 0x2: + ret = 0; /* neg underflow */ + break; + case 0x3: + ret = 0x8000000000000001; /* negative overflow */ + break; + } +#endif *cc = CC; /* return CC's */ return ret; /* return result */ DOVFLO: CC |= CC4BIT; /* set CC4 for exponent overflow */ DUNFLO: - ret = temp; /* get return value */ + ret = dfrac; /* get return value */ CC |= CC1BIT; /* set CC1 for arithmetic exception */ - if (temp & DMSIGN) { + if (dfrac & DMSIGN) { CC |= CC3BIT; /* set neg fraction bit CC3 */ } else { CC |= CC2BIT; /* set pos fraction bit CC2 */ } goto goout2; /* go set cc's and return */ } +#endif /* subtract memory floating point number from register floating point number */ t_uint64 s_sufd(t_uint64 reg, t_uint64 mem, uint32 *cc) { @@ -907,7 +1221,8 @@ setcc: /* convert from 64 bit double to 64 bit integer */ /* set CC1 if overflow/underflow exception */ t_uint64 s_fixd(t_uint64 dblv, uint32 *cc) { - uint32 temp2, CC = 0, neg = 0, sc = 0; +// uint32 temp2, CC = 0, neg = 0, sc = 0; + int32 temp2, CC = 0, neg = 0, sc = 0; t_uint64 dest; /* neg and CC flags already set to zero */ @@ -1294,6 +1609,7 @@ t_uint64 s_mpfd(t_uint64 reg, t_uint64 mem, uint32 *cc) { /* gt 0, fall through */ } /* operator is positive here */ +//#define DEXMASK 0x7f00000000000000LL /* double exponent mask */ dblreg = mem & DEXMASK; /* extract exponent */ mem ^= dblreg; /* zero exponent to make fraction */ expm = (uint32)(dblreg >> 32); /* get operator exponent as 32 bit value */ @@ -1312,6 +1628,7 @@ t_uint64 s_mpfd(t_uint64 reg, t_uint64 mem, uint32 *cc) { /* gt 0, fall through */ } /* operand is positive here */ +//#define DEXMASK 0x7f00000000000000LL /* double exponent mask */ dblreg = reg & DEXMASK; /* extract exponent */ reg ^= dblreg; /* zero exponent to make fraction */ expr = (uint32)(dblreg >> 32); /* get operand exponent as 32 bit value */ @@ -1361,9 +1678,11 @@ t_uint64 s_mpfd(t_uint64 reg, t_uint64 mem, uint32 *cc) { goto DUNFLO; /* process underflow. */ dtemp2 = ((t_uint64)temp) << 32; /* move exp into upper 32 bits */ dblreg = ((t_int64)dblreg) >> 7; /* adjust fraction */ +//#define DFRMASK 0x80ffffffffffffffll /* fraction mask */ dblreg &= DFRMASK; /* mask out exponent field */ if (dblreg != 0) { /* see if 0, if so return 0 */ if (dblreg & DMSIGN) /* see if negative */ +//#define DEXMASK 0x7f00000000000000LL /* double exponent mask */ dtemp2 ^= DEXMASK; /* negative fraction, complement exp */ dblreg |= dtemp2; /* combine exponent and fraction */ } @@ -1424,6 +1743,7 @@ t_uint64 s_dvfd(t_uint64 reg, t_uint64 mem, uint32 *cc) { /* gt 0, fall through */ } /* operator is positive here */ +//#define DEXMASK 0x7f00000000000000LL /* double exponent mask */ dblreg = mem & DEXMASK; /* extract exponent */ mem ^= dblreg; /* zero exponent to make fraction */ expm = (uint32)(dblreg >> 32); /* get operator exponent as 32 bit value */ @@ -1444,6 +1764,7 @@ t_uint64 s_dvfd(t_uint64 reg, t_uint64 mem, uint32 *cc) { /* gt 0, fall through */ } /* operand is positive here */ +//#define DEXMASK 0x7f00000000000000LL /* double exponent mask */ dblreg = reg & DEXMASK; /* extract exponent */ reg ^= dblreg; /* zero exponent to make fraction */ expr = (uint32)(dblreg >> 32); /* get operand exponent as 32 bit value */ @@ -1494,7 +1815,7 @@ t_uint64 s_dvfd(t_uint64 reg, t_uint64 mem, uint32 *cc) { /* normalize the value in dblreg and put exponent into expr */ dblreg = s_nord(dblreg, &expr); /* normalize fraction */ if (dblreg == DMSIGN) { /* check for neg zero */ - dblreg = DNORMASK; /* correct the value */ + dblreg = DNORMASK; /* correct the value */ expr++; /* adjust exponent too */ } expr <<= 24; /* reposition normalization count */ @@ -1513,9 +1834,11 @@ t_uint64 s_dvfd(t_uint64 reg, t_uint64 mem, uint32 *cc) { goto DUNFLO; /* process underflow. */ dtemp2 = ((t_uint64)temp) << 32; /* move exp into upper 32 bits */ dblreg = ((t_int64)dblreg) >> 7; /* adjust fraction */ +//#define DFRMASK 0x80ffffffffffffffll /* fraction mask */ dblreg &= DFRMASK; /* mask out exponent field */ if (dblreg != 0) { /* see if 0, if so return 0 */ if (dblreg & DMSIGN) /* see if negative */ +//#define DEXMASK 0x7f00000000000000LL /* double exponent mask */ dtemp2 ^= DEXMASK; /* negative fraction, complement exp */ dblreg |= dtemp2; /* combine exponent and fraction */ } @@ -1562,3 +1885,632 @@ setcc: *cc = CC; /* return CC's */ return dblreg; /* return result */ } + +//#define DEXMASK 0x7f00000000000000LL /* double exponent mask */ +#define DMMASK 0x00ffffffffffffffLL /* double mantissa mask */ +#define DCMASK 0x1000000000000000LL /* double carry mask */ +#define DIBMASK 0x0fffffffffffffffLL /* double fp nibble mask */ +#define DUMASK 0x0ffffffffffffff0LL /* double fp mask */ +#define DNMASK 0x0f00000000000000LL /* double nibble mask */ +#define DZMASK 0x00f0000000000000LL /* shifted nibble mask */ + +#ifdef USE_NEW +/* add memory floating point number to register floating point number */ +/* set CC1 if overflow/underflow */ +/* use revised normalization code */ +t_uint64 n_adfd(t_uint64 reg, t_uint64 mem, uint32 *cc, uint32 type) +{ + u_int64_t res; + uint8 sign = 0; + int er, em, temp; + uint32 CC = 0; + + *cc = 0; /* clear the CC'ss */ + + sim_debug(DEBUG_EXP, &cpu_dev, + "ADFD entry mem %016lx reg %016lx\n", mem, reg); + /* process the memory operand value */ + /* extract exponent and mantissa */ +//#define DEXMASK 0x7f00000000000000LL /* double exponent mask */ + em = (mem & DEXMASK) >> 56; /* extract mem exponent */ + if (mem & DMSIGN) { /* mem negative */ + sign |= MEMNEG; /* set neg flag (1) */ + mem = NEGATE32(mem); /* negate number */ + em ^= 0x7f; /* complement exp */ + } +//#define DMMASK 0x00ffffffffffffffLL /* double mantissa mask */ + mem &= DMMASK; /* get mem mantissa */ + + /* normalize the memory mantissa */ + if (mem != 0) { /* check for zero value */ +//#define DNMASK 0x0f00000000000000LL /* double nibble mask */ + while ((mem != 0) && (mem & DNMASK) == 0) { + mem <<= 4; /* adjust mantisa by a nibble */ + em--; /* and adjust exponent smaller by 1 */ + } + } + + /* process the register operand value */ + /* extract exponent and mantissa */ +//#define DEXMASK 0x7f00000000000000LL /* double exponent mask */ + er = (reg & DEXMASK) >> 56; /* extract reg exponent */ + if (reg & DMSIGN) { /* reg negative */ + sign |= REGNEG; /* set neg flag (2) */ + reg = NEGATE32(reg); /* negate number */ + er ^= 0x7f; /* complement exp */ + } +//#define DMMASK 0x00ffffffffffffffLL /* double mantissa mask */ + reg &= DMMASK; /* get reg mantissa */ + + /* normalize the register mantissa */ + if (reg != 0) { /* check for zero value */ +//#define DNMASK 0x0f00000000000000LL /* double nibble mask */ + while ((reg != 0 ) && (reg & DNMASK) == 0) { + reg <<= 4; /* adjust mantisa by a nibble */ + er--; /* and adjust exponent smaller by 1 */ + } + } + + mem = mem << 4; /* align mem for normalization */ + reg = reg << 4; /* align reg for normalization */ + + /* subtract memory exp from reg exp */ + temp = er - em; /* get the signed exp difference */ + + if (temp > 0) { /* reg exp > mem exp */ + if (temp > 15) { + mem = 0; /* if too much difference, make zero */ + sign &= ~MEMNEG; /* is reg value negative */ + } else + /* Shift mem right if reg larger */ + mem >>= (4 * temp); /* adjust for exponent difference */ + } else + if (temp < 0) { /* reg < mem exp */ + if (temp < -15) { + reg = 0; /* if too much difference, make zero */ + sign &= ~REGNEG; /* is reg value negative */ + } else + /* Shift reg right if mem larger */ + reg >>= (4 * (-temp)); /* adjust for exponent difference */ + er = em; /* make exponents the same */ + } + + /* er now has equal exponent for both values */ + /* add results */ +// if (sign == 2 || sign == 1) { + if (sign == REGNEG || sign == MEMNEG) { + /* different signs so do subtract */ +//#define DIBMASK 0x0fffffffffffffffLL /* double fp nibble mask */ + mem ^= DIBMASK; /* complement the value and inc */ + mem++; /* negate all but upper nibble */ + res = reg + mem; /* add the values */ +//#define DCMASK 0x1000000000000000LL /* double carry mask */ + if (res & DCMASK) { /* see if carry */ + res &= DIBMASK; /* clear off the carry bit */ + } else { +// sign ^= 2; /* flip the sign */ + sign ^= REGNEG; /* flip the sign (2) */ + res ^= DIBMASK; /* and negate the value */ + res++; /* negate all but the upper nibble */ + } + } else { + res = reg + mem; /* same sign, just add */ + } + + sim_debug(DEBUG_EXP, &cpu_dev, + "ADFD test OVF res %016lx er %02x sign %01x\n", res, er, sign); + /* If overflow, shift right 4 bits */ + CC = 0; +//#define DCMASK 0x1000000000000000LL /* double carry mask */ + if (res & DCMASK) { /* see if overflow carry */ + res >>= 4; /* move mantissa down 4 bits */ + er++; /* and adjust exponent */ + if (er >= 0x80) { /* if exponent is too large, overflow */ + /* OVERFLOW */ + CC = CC1BIT|CC4BIT; /* set arithmetic overflow */ + /* set CC2 & CC3 on exit */ + sim_debug(DEBUG_EXP, &cpu_dev, + "OVERFLOW res %016lx er %02x sign %01x\n", res, er, sign); + CC |= (sign & 2)?CC3BIT:CC2BIT; /* neg is CC3, pos is CC2 */ + if (CC & CC3BIT) { /* NEG overflow? */ + if (type & FPADD) /* is this single FP instruction */ + res = 0x8000000100000000; /* yes */ + else + res = 0x8000000000000001; /* doouble yes */ + } else + res = 0x7FFFFFFFFFFFFFFF; /* no, pos */ + goto goout; + } + } + +#ifdef MOVE + /* Set condition codes */ + if (type & FPADD) { /* was this an add instruction */ + if (res != 0) /* see if non zero */ +// CC |= (sign & 2) ? 1 : 2; + CC |= (sign & 2)?CC3BIT:CC2BIT; /* neg is CC3, pos is CC2 */ + else { + er = sign = 0; /* we have zero CC4 */ + CC |= CC4BIT; /* set zero cc */ + } + } else { /* must be subtract */ +//#define DUMASK 0x0ffffffffffffff0LL /* double fp mask */ + if ((res & DUMASK) != 0) /* mantissa not zero */ + CC |= (sign & 2)?CC3BIT:CC2BIT; /* neg is CC3, pos is CC2 */ + else { + res = er = sign = 0; /* we have zero CC4 */ + CC |= CC4BIT; /* set zero cc */ + } + } +#endif + + /* normalize the fraction */ + if (res != 0) { /* check for zero value */ + while ((res != 0) && (res & DNMASK) == 0) { + res <<= 4; /* adjust mantisa by a nibble */ + er--; /* and adjust exponent smaller by 1 */ + } + /* Check if exponent underflow */ + if (er < 0) { + /* UNDERFLOW */ + sim_debug(DEBUG_EXP, &cpu_dev, + "UNDERFLOW res %016lx er %02x sign %01x\n", res, er, sign); + CC |= CC1BIT; /* set arithmetic exception */ + CC |= (sign & 2)?CC3BIT:CC2BIT; /* neg is CC3, pos is CC2 */ + res = 0; /* make all zero */ + sign = er = 0; /* zero */ + goto goout; + } + } else { + /* result is zero */ + sign = er = 0; /* make abs zero */ + CC = CC4BIT; /* zero value */ + } + + res >>= 4; /* remove the carryout nibble */ +//#define DMMASK 0x00ffffffffffffffLL /* double mantissa mask */ + res &= DMMASK; /* clear exponent */ + +//#define DEXMASK 0x7f00000000000000LL /* double exponent mask */ + res |= ((((u_int64_t)er) << 56) & DEXMASK); /* merge exp and mantissa */ +#ifndef MOVE + /* Set condition codes */ + if (type & FPADD) { /* was this an add instruction */ + if (res != 0) /* see if non zero */ +// CC |= (sign & 2) ? 1 : 2; + CC |= (sign & 2)?CC3BIT:CC2BIT; /* neg is CC3, pos is CC2 */ + else { + er = sign = 0; /* we have zero CC4 */ + CC |= CC4BIT; /* set zero cc */ + } + } else { /* must be subtract */ +//#define DUMASK 0x0ffffffffffffff0LL /* double fp mask */ + if ((res & DUMASK) != 0) /* mantissa not zero */ + CC |= (sign & 2)?CC3BIT:CC2BIT; /* neg is CC3, pos is CC2 */ + else { + res = er = sign = 0; /* we have zero CC4 */ + CC |= CC4BIT; /* set zero cc */ + } + } +#endif +goout: + /* store results */ + *cc = CC; /* save CC's */ +//#define DEXMASK 0x7f00000000000000LL /* double exponent mask */ +// res |= ((((u_int64_t)er) << 56) & DEXMASK); /* merge exp and mantissa */ + /* if result not zero and reg or mem is negative, make negative */ + //FIXME ?? +// if (((CC & CC4BIT) == 0) && (sign & 3)) /* is result to be negative */ +// res = NEGATE32(res); /* make value negative */ + if (((CC & CC4BIT) == 0) && ((sign == 0) || (sign == 3))) + if (!((res > 0) && (sign == 0))) + res = NEGATE32(res); /* make negative */ + return res; /* return results */ + +#ifdef NOTNOW + /* come here to set cc's and return */ + /* temp has return value */ +//goout: + if (ret & DMSIGN) + CC |= CC3BIT; /* CC3 for neg */ + else + if (ret == 0) + CC |= CC4BIT; /* CC4 for zero */ + else + CC |= CC2BIT; /* CC2 for greater than zero */ +goout2: + /* return temp to destination reg */ + *CC = cc; /* return CC's */ + return ret; /* return result */ + +DOVFLO: + CC |= CC4BIT; /* set CC4 for exponent overflow */ +DUNFLO: + ret = temp; /* get return value */ + CC |= CC1BIT; /* set CC1 for arithmetic exception */ + if (temp & DMSIGN) { + CC |= CC3BIT; /* set neg fraction bit CC3 */ + } else { + CC |= CC2BIT; /* set pos fraction bit CC2 */ + } + goto goout2; /* go set cc's and return */ +#endif +} +#endif + +#ifdef USE_NEW_MUL +/* multiply register floating point number by memory floating point number */ +/* set CC1 if overflow/underflow */ +/* use revised normalization code */ +t_uint64 n_mpfd(t_uint64 reg, t_uint64 mem, uint32 *cc) { + u_int64_t res; + uint8 sign; + int er, em, temp; + uint32 CC; + + *cc = 0; /* clear the CC'ss */ + CC = 0; /* clear local CC's */ + + sim_debug(DEBUG_EXP, &cpu_dev, + "MPFD entry mem %016lx reg %016lx\n", mem, reg); + sign = 0; + /* process the memory operand value */ + /* extract exponent and mantissa */ +//#define DEXMASK 0x7f00000000000000LL /* double exponent mask */ + em = (mem & DEXMASK) >> 56; /* extract mem exponent */ + if (mem & DMSIGN) { /* mem negative */ +// sign |= 1; /* set neg flag */ + sign |= MEMNEG; /* set neg flag */ + mem = NEGATE32(mem); /* complement exp */ + em ^= 0x7f; /* complement exp */ + } +//#define DMMASK 0x00ffffffffffffffLL /* double mantissa mask */ + mem &= DMMASK; /* get mem mantissa */ +// mem = mem << 4; /* align mem for normalization */ + + /* process the register operand value */ + /* extract exponent and mantissa */ +//#define DEXMASK 0x7f00000000000000LL /* double exponent mask */ + er = (reg & DEXMASK) >> 56; /* extract reg exponent */ + if (reg & DMSIGN) { /* reg negative */ +// sign |= 2; /* set neg flag */ + sign |= REGNEG; /* set neg flag (2) */ + reg = NEGATE32(reg); /* complement exp */ + er ^= 0x7f; /* complement exp */ + } +//#define DMMASK 0x00ffffffffffffffLL /* double mantissa mask */ + reg &= DMMASK; /* get reg mantissa */ +// reg = reg << 4; /* align reg for normalization */ + + /* normalize the memory mantissa */ + if (mem != 0) { /* check for zero value */ +//#define DNMASK 0x0f00000000000000LL /* double nibble mask */ + while ((mem != 0) && (mem & DNMASK) == 0) { + mem <<= 4; /* adjust mantisa by a nibble */ + em--; /* and adjust exponent smaller by 1 */ + } + } + + /* normalize the register mantissa */ + if (reg != 0) { /* check for zero value */ +//#define DNMASK 0x0f00000000000000LL /* double nibble mask */ + while ((mem != 0) && (reg & DNMASK) == 0) { + reg <<= 4; /* adjust mantisa by a nibble */ + er--; /* and adjust exponent smaller by 1 */ + } + } + + er = er + em - 0x40; /* get the exp value */ + + res = 0; /* zero result for multiply */ + /* multiply by doing shifts and adds */ +// for (temp = 0; temp < 56; temp++) { + for (temp = 0; temp < 60; temp++) { + /* Add if we need too */ + if (reg & 1) + res += mem; + /* Shift right by one */ + reg >>= 1; + res >>= 1; + } + er++; /* adjust exp for extra nible shift */ + + /* If overflow, shift right 4 bits */ +//#define DCMASK 0x1000000000000000LL /* double carry mask */ +// if (res & DCMASK) { /* see if overflow carry */ +//#define DEXMASK 0x7f00000000000000LL /* double exponent mask */ + if (res & DEXMASK) { /* see if overflow carry */ + res >>= 4; /* move mantissa down 4 bits */ + er++; /* and adjust exponent */ + if (er >= 0x80) { /* if exponent is too large, overflow */ + /* OVERFLOW */ + res = 0x7fffffffffffffffll; /* too big, set max */ + CC = CC1BIT; /* set arithmetic exception */ + } + } + + /* Align the results */ + if (res != 0) { +//#define DZMASK 0x00f0000000000000LL /* double nibble mask */ + while ((res != 0) && (res & DZMASK) == 0) { + res <<= 4; /* move over mantessa */ + er--; /* reduce exponent cocunt by 1 */ + } + if (er < 0) { /* check if rxponent underflow */ + /* UNDERFLOW */ + res = 0; /* make return value zero */ + sign = er = 0; + CC |= CC1BIT; /* set arithmetic exception */ + CC |= CC4BIT; /* set zero value CC */ + } + } else { + er = sign = 0; + CC |= CC4BIT; /* set zero value CC */ + } + +//#define DMMASK 0x00ffffffffffffffLL /* double mantissa mask */ + res &= DMMASK; /* clear exponent */ +//#define DEXMASK 0x7f00000000000000LL /* double exponent mask */ + res |= ((((u_int64_t)er) << 56) & DEXMASK); /* merge exp and mantissa */ + if (sign == 2 || sign == 1) /* is result to be negative */ + res = NEGATE32(res); /* make value negative */ + + /* determine CC's for result */ + CC = 0; + if (res != 0) /* see if non zero */ + CC = (sign & 2)?CC3BIT:CC2BIT; /* neg is CC3, pos is CC2 */ + else { + er = sign = 0; /* we have zero CC4 */ + CC = CC4BIT; /* set zero cc */ + } + *cc = CC; /* save CC's */ + return res; /* return results */ + +#ifdef NOTNOW + /* come here to set cc's and return */ + /* temp has return value */ +goout: + if (ret & DMSIGN) + CC |= CC3BIT; /* CC3 for neg */ + else + if (ret == 0) + CC |= CC4BIT; /* CC4 for zero */ + else + CC |= CC2BIT; /* CC2 for greater than zero */ +goout2: + /* return temp to destination reg */ + *cc = CC; /* return CC's */ + return ret; /* return result */ + +DOVFLO: + CC |= CC4BIT; /* set CC4 for exponent overflow */ +DUNFLO: + ret = temp; /* get return value */ + CC |= CC1BIT; /* set CC1 for arithmetic exception */ + if (temp & DMSIGN) { + CC |= CC3BIT; /* set neg fraction bit CC3 */ + } else { + CC |= CC2BIT; /* set pos fraction bit CC2 */ + } + goto goout2; /* go set cc's and return */ +#endif +} +#endif + +#ifdef USE_NEW_DIV +/* divide register floating point number by memory floating point number */ +/* set CC1 if overflow/underflow */ +/* use revised normalization code */ +t_uint64 n_dvfd(t_uint64 reg, t_uint64 mem, uint32 *cc) { + t_uint64 res; + char sign; + int er, em, temp; + uint32 CC; + + *cc = 0; /* clear the CC'ss */ + CC = 0; /* clear local CC's */ + + sign = 0; + /* process the memory operand value */ + /* extract exponent and mantissa */ +//#define DEXMASK 0x7f00000000000000LL /* double exponent mask */ + em = (mem & DEXMASK) >> 56; /* extract mem exponent */ + if (mem & DMSIGN) { /* mem negative */ + sign |= 1; /* set neg flag */ + mem = NEGATE32(mem); /* complement exp */ + em ^= 0x7f; /* complement exp */ + } +//#define DMMASK 0x00ffffffffffffffLL /* double mantissa mask */ + mem &= DMMASK; /* get mem mantissa */ +// mem = mem << 4; /* align mem for normalization */ + + /* process the register operand value */ + /* extract exponent and mantissa */ +//#define DEXMASK 0x7f00000000000000LL /* double exponent mask */ + er = (reg & DEXMASK) >> 56; /* extract reg exponent */ + if (reg & DMSIGN) { /* reg negative */ + sign |= 2; /* set neg flag */ + reg = NEGATE32(reg); /* complement exp */ + er ^= 0x7f; /* complement exp */ + } +//#define DMMASK 0x00ffffffffffffffLL /* double mantissa mask */ + reg &= DMMASK; /* get reg mantissa */ +// reg = reg << 4; /* align reg for normalization */ + +//printf("DV etr mem %016lx em %02x %.12e\n\r", mem, em, dfpval(mem)); +//printf("DV etr reg %016lx er %02x %.12e\n\r", reg, er, dfpval(reg)); + /* normalize the memory mantissa */ + if (mem != 0) { /* check for zero value */ +//#define DNMASK 0x0f00000000000000LL /* double nibble mask */ + while ((mem & DNMASK) == 0) { + mem <<= 4; /* adjust mantisa by a nibble */ + em--; /* and adjust exponent smaller by 1 */ + } + } +//printf("DV nor mem %016lx em %02x %.12e\n\r", mem, em, dfpval(mem)); + + /* see if division by zero */ + if (mem == 0) { + printf("DV Division by zero\n\r"); + } + + /* normalize the register mantissa */ + if (reg != 0) { /* check for zero value */ +//#define DNMASK 0x0f00000000000000LL /* double nibble mask */ + while ((reg & DNMASK) == 0) { + reg <<= 4; /* adjust mantisa by a nibble */ + er--; /* and adjust exponent smaller by 1 */ + } + } +//printf("DV nor reg %016lx er %02x em %02x %.12e\n\r", reg, er, em, dfpval(reg)); + + er = er - em + 0x40; /* get the exp value */ + + /* move left 1 nubble for divide */ +//? reg <<= 4; +//? mem <<= 4; + + /* see if we need to adjust divisor if larger that dididend */ + if (reg > mem) { + reg >>= 4; + er++; + } + +//#define DIBMASK 0x0fffffffffffffffLL /* double nibble mask */ +// mem ^= XMASKL; /* change sign of mem val to do add */ + mem ^= DIBMASK; /* change sign of mem val to do add */ + mem++; /* comp & incr */ + +//printf("DV exp er %02x\n\r",er); + res = 0; /* zero result for multiply */ + /* do divide by using shift & add (subt) */ +// for (temp = 0; temp < 56; temp++) { +// for (temp = 56; temp > 0; temp--) { +// for (temp = 0; temp < 60; temp++) { + for (temp = 56; temp > 0; temp--) { + t_uint64 tmp; + +//printf("DV div reg %016lx mem %016lx res %016lx temp %02x\n\r", reg, mem, res, temp); + /* Add if we need too */ + /* Shift left by one */ + reg <<= 1; + /* Subtract remainder to dividend */ + tmp = reg + mem; + +//printf("DV div reg %016lx mem %016lx res %016lx temp %02x\n\r", reg, mem, res, temp); + /* Shift quotent left one bit */ + res <<= 1; + + /* If remainder larger then divisor replace */ +// if ((tmp & CMASKL) != 0) { +//#define DCMASK 0x1000000000000000LL /* double carry mask */ + if ((tmp & DCMASK) != 0) { + reg = tmp; + res |= 1; + } + } + + /* Compute one final set to see if rounding needed */ + /* Shift left by one */ + reg <<= 1; + /* Subtract remainder to dividend */ + reg += mem; + +#ifndef TRUNCATE + /* If .5 off, round */ +//#define DMSIGN 0x8000000000000000LL /* 64 bit minus sign */ +// if ((reg & MSIGNL) != 0) { + if ((reg & DMSIGN) != 0) { +//printf("DV diva reg %016lx mem %016lx res %016lx temp %02x\n\r", reg, mem, res, temp); + res++; + } +#endif +//printf("DV aft mpy res %016lx er %02x\n\r",res, er); + + /* If overflow, shift right 4 bits */ +//#define DCMASK 0x1000000000000000LL /* double carry mask */ +// if (res & DCMASK) { /* see if overflow carry */ +// if (res & 0x0100000000000000LL) { /* see if overflow carry */ +// if (res & 0x0300000000000000LL) { /* see if overflow carry */ +// if (res & EMASKL) { /* see if overflow carry */ +//#define DEXMASK 0x7f00000000000000ll /* exponent mask */ + if (res & DEXMASK) { /* see if overflow carry */ + res >>= 4; /* move mantissa down 4 bits */ + er++; /* and adjust exponent */ + if (er >= 0x80) { /* if exponent is too large, overflow */ + /* OVERFLOW */ + res = 0x7fffffffffffffffll; /* too big, set max */ + CC = CC1BIT; /* set arithmetic exception */ + } + } + + /* Align the results */ + if ((res) != 0) { +//#define DZMASK 0x00f0000000000000LL /* double nibble mask */ + while ((res & DZMASK) == 0) { + res <<= 4; + er--; + } + /* Check if underflow */ + if (er < 0) { + /* UNDERFLOW */ + res = 0; /* make return value zero */ + sign = er = 0; + CC |= CC1BIT; /* set arithmetic exception */ + CC |= CC4BIT; /* set zero value CC */ + } + } else { + er = sign = 0; + CC |= CC4BIT; /* set zero value CC */ + } + +//#define DMMASK 0x00ffffffffffffffLL /* double mantissa mask */ +// res &= DMMASK; /* clear exponent */ + res &= 0x00fffffffffffff0LL; /* clear exponent */ +//#define DEXMASK 0x7f00000000000000LL /* double exponent mask */ + res |= ((((t_uint64)er) << 56) & DEXMASK); /* merge exp and mantissa */ + if (sign == 2 || sign == 1) /* is result to be negative */ + res = NEGATE32(res); /* make value negative */ + + /* determine CC's for result */ + CC = 0; + if (res != 0) /* see if non zero */ + CC = (sign & 2)?CC3BIT:CC2BIT; /* neg is CC3, pos is CC2 */ + else { + er = sign = 0; /* we have zero CC4 */ + CC = CC4BIT; /* set zero cc */ + } + *cc = CC; /* save CC's */ + return res; /* return results */ + +#ifdef NOTNOW + /* come here to set cc's and return */ + /* temp has return value */ +goout: + if (ret & DMSIGN) + CC |= CC3BIT; /* CC3 for neg */ + else + if (ret == 0) + CC |= CC4BIT; /* CC4 for zero */ + else + CC |= CC2BIT; /* CC2 for greater than zero */ +goout2: + /* return temp to destination reg */ + *cc = CC; /* return CC's */ + return ret; /* return result */ + +DOVFLO: + CC |= CC4BIT; /* set CC4 for exponent overflow */ +DUNFLO: + ret = temp; /* get return value */ + CC |= CC1BIT; /* set CC1 for arithmetic exception */ + if (temp & DMSIGN) { + CC |= CC3BIT; /* set neg fraction bit CC3 */ + } else { + CC |= CC2BIT; /* set pos fraction bit CC2 */ + } + goto goout2; /* go set cc's and return */ +#endif +} +#endif +