From 1f70fc9ba0e301c829a12e10cf196fe4983807fd Mon Sep 17 00:00:00 2001 From: AZBevier Date: Mon, 13 Jul 2020 19:01:16 -0700 Subject: [PATCH] SEL32: Do general cleanup and removal of conditional debug code. SEL32: Update and validate ADFW/SUFW, ADFD/SUFD, MPFD, & DVFD fp code. SEL32: Update readme files. SEL32: --- README.md | 16 +- SEL32/README.md | 10 +- SEL32/sel32_chan.c | 518 +++++---- SEL32/sel32_clk.c | 82 +- SEL32/sel32_com.c | 91 +- SEL32/sel32_con.c | 148 +-- SEL32/sel32_cpu.c | 569 +++------- SEL32/sel32_defs.h | 3 + SEL32/sel32_disk.c | 91 +- SEL32/sel32_fltpt.c | 2387 ++++++++++++++---------------------------- SEL32/sel32_hsdp.c | 206 +--- SEL32/sel32_iop.c | 27 +- SEL32/sel32_lpr.c | 211 ++-- SEL32/sel32_mfp.c | 22 +- SEL32/sel32_mt.c | 196 +--- SEL32/sel32_scfi.c | 39 +- SEL32/sel32_scsi.c | 52 +- SEL32/sel32_sys.c | 8 +- SEL32/tests/diag.ini | 6 +- 19 files changed, 1466 insertions(+), 3216 deletions(-) diff --git a/README.md b/README.md index 1d6b8d5..feb79ce 100644 --- a/README.md +++ b/README.md @@ -172,9 +172,9 @@ Support for the following units: # SEL32 Development Simulator -This is a working copy of a simulator for the SEL Concept/32 computer. -The current test version is for the SEL 32/27, 32/67, 32/87, 32/97 computers. -Support for 32/55, 32/75, V6, and V9 computers may be added in the future. +This is a working simulator for the SEL Concept/32 line of computers. The +current test version is for the SEL 32/27, 32/67, 32/87, 32/97, V6, and V9 +computers. Support for 32/55, and 32/75 computers may be added in the future. This simulator is co-authors with James C. Bevier. I did the initial parts of the simulator, James took it to a working simulator, I am assisting him in maintaining and enhancing the simulator. This simulator is running a test @@ -183,8 +183,14 @@ from a SDT tape. The disk image can be booted, initialized, and run many of the MPX utilities; including OPCOM & TSM. Eight terminals can be used to access TSM via Telnet port 4747. Initial support has been added for excess 64 floating point arithmetic. More testing is still required. The sim32disk.gz -can be uncompressed and booted with the sel32.27.sim32.disk.ini initialization file. -The sim32sdt.tap.gz file can also be uncompressed and started with the +can be uncompressed and booted with the sel32.27.sim32.disk.ini initialization +file. The sim32sdt.tap.gz file can also be uncompressed and started with the sel32.27.sim32.tape.ini initialization file to install from tape. +The current version can also install and run UTX 2.1A from an install tape. +It is the SEL version of System V Unix and BSD Unix ported to the V6 and V9 +processors. It can run in single or multi user mode. UTX utilizes the basemode +instruction set and a virtual memory system provided by the V6 & V9 CPUs. +There are still some random halts and panics. The system needs further +testing to solidify the SEL32 simulator code. diff --git a/SEL32/README.md b/SEL32/README.md index 6ecb25e..7565ffd 100644 --- a/SEL32/README.md +++ b/SEL32/README.md @@ -4,7 +4,7 @@ This is a working copy of a simulator for the SEL Concept/32 computer. The current test version is for the SEL 32/27, 32/67, 32/77, 32/87, 32/97, V6, and V9 computers. All of the processors except for the -32/77 can run Gould diags. Support for 32/55 computers may be added +32/77 can run the Gould diags. Support for 32/55 computers may be added in the future. # SEL Concept/32 @@ -77,8 +77,8 @@ diag.tap bootable level one diagnostic tape w/auto testing. Set Available UTX-21a install tape for testing: utxtape1.ini command file to start UTX install tape. ./sel32 utxtape1.ini utx21a1.tap bootable UTX install tape for testing basemode. The current - V6 & V9 will boot UTX into single user mode. You can run a - small subset of the commands that are on the installation tape. + V6 & V9 will boot UTX into single/multi user mode. You can run + the full set of the commands that are on the installation tapes. Prep, the disk preparation UTX program, can format a disk drive. Other file systems can be created and saves restored. All basemode instructions have been tested with the CV.BRD diag. @@ -90,8 +90,8 @@ Other MPX verion support: I am still looking for an MPX 3.X user or master SDT tape. I have much of the source, but no loadable code to create a bootable system. Please keep looking for anyone who can provide these tapes or a - disk image of a bootable system.. + disk image of a bootable system. James C. Bevier -05/19/2020 +06/30/2020 diff --git a/SEL32/sel32_chan.c b/SEL32/sel32_chan.c index 6e7fbd2..283d025 100644 --- a/SEL32/sel32_chan.c +++ b/SEL32/sel32_chan.c @@ -1,7 +1,7 @@ /* sel32_chan.c: SEL 32 Channel functions. Copyright (c) 2018-2020, James C. Bevier - Portions provided by Richard Cornwell and other SIMH contributers + Portions provided by Richard Cornwell, Geert Rolf and other SIMH contributers Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -78,47 +78,54 @@ /* Bits 16-23 - Channel address (0-127) */ /* Bits 24-31 - Device Sub address (0-255) */ -uint32 channels = MAX_CHAN; /* maximum number of channels */ -int subchannels = SUB_CHANS; /* maximum number of subchannel devices */ -int irq_pend = 0; /* pending interrupt flag */ +uint32 channels = MAX_CHAN; /* maximum number of channels */ +int subchannels = SUB_CHANS; /* maximum number of subchannel devices */ +int irq_pend = 0; /* pending interrupt flag */ -extern uint32 CPUSTATUS; /* CPU status word */ -extern uint32 INTS[]; /* Interrupt status flags */ +#define GEERT_UNDO +#ifndef GEERT_UNDO +int ScanCycles = 0; +int DoNextCycles = 0; +#include +#endif -DIB *dib_unit[MAX_DEV]; /* Pointer to Device info block */ -DIB *dib_chan[MAX_CHAN]; /* pointer to channel mux dib */ -uint16 loading; /* set when booting */ +extern uint32 CPUSTATUS; /* CPU status word */ +extern uint32 INTS[]; /* Interrupt status flags */ -#define get_chan(chsa) ((chsa>>8)&0x7f) /* get channel number from ch/sa */ +DIB *dib_unit[MAX_DEV]; /* Pointer to Device info block */ +DIB *dib_chan[MAX_CHAN]; /* pointer to channel mux dib */ +uint16 loading; /* set when booting */ + +#define get_chan(chsa) ((chsa>>8)&0x7f) /* get channel number from ch/sa */ /* forward definitions */ -CHANP *find_chanp_ptr(uint16 chsa); /* find chanp pointer */ -UNIT *find_unit_ptr(uint16 chsa); /* find unit pointer */ -int chan_read_byte(uint16 chsa, uint8 *data); -int chan_write_byte(uint16 chsa, uint8 *data); -void set_devattn(uint16 chsa, uint16 flags); -void set_devwake(uint16 chsa, uint16 flags); /* wakeup O/S for async line */ -void chan_end(uint16 chsa, uint16 flags); -int test_write_byte_end(uint16 chsa); -t_stat checkxio(uint16 chsa, uint32 *status); /* check XIO */ -t_stat startxio(uint16 chsa, uint32 *status); /* start XIO */ -t_stat testxio(uint16 chsa, uint32 *status); /* test XIO */ -t_stat stoptxio(uint16 chsa, uint32 *status); /* stop XIO */ -t_stat rschnlxio(uint16 chsa, uint32 *status); /* reset channel XIO */ -t_stat haltxio(uint16 chsa, uint32 *status); /* halt XIO */ -t_stat grabxio(uint16 chsa, uint32 *status); /* grab XIO n/u */ -t_stat rsctlxio(uint16 chsa, uint32 *status); /* reset controller XIO */ -uint32 find_int_icb(uint16 chsa); -uint32 find_int_lev(uint16 chsa); -uint32 scan_chan(uint32 *ilev); -t_stat set_inch(UNIT *uptr, uint32 inch_addr); /* set channel inch address */ -t_stat chan_boot(uint16 chsa, DEVICE *dptr); -t_stat chan_set_devs(); -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); +CHANP *find_chanp_ptr(uint16 chsa); /* find chanp pointer */ +UNIT *find_unit_ptr(uint16 chsa); /* find unit pointer */ +int chan_read_byte(uint16 chsa, uint8 *data); +int chan_write_byte(uint16 chsa, uint8 *data); +void set_devattn(uint16 chsa, uint16 flags); +void set_devwake(uint16 chsa, uint16 flags); /* wakeup O/S for async line */ +void chan_end(uint16 chsa, uint16 flags); +int test_write_byte_end(uint16 chsa); +t_stat checkxio(uint16 chsa, uint32 *status); /* check XIO */ +t_stat startxio(uint16 chsa, uint32 *status); /* start XIO */ +t_stat testxio(uint16 chsa, uint32 *status); /* test XIO */ +t_stat stoptxio(uint16 chsa, uint32 *status); /* stop XIO */ +t_stat rschnlxio(uint16 chsa, uint32 *status); /* reset channel XIO */ +t_stat haltxio(uint16 chsa, uint32 *status); /* halt XIO */ +t_stat grabxio(uint16 chsa, uint32 *status); /* grab XIO n/u */ +t_stat rsctlxio(uint16 chsa, uint32 *status); /* reset controller XIO */ +uint32 find_int_icb(uint16 chsa); +uint32 find_int_lev(uint16 chsa); +uint32 scan_chan(uint32 *ilev); +t_stat set_inch(UNIT *uptr, uint32 inch_addr); /* set channel inch address */ +t_stat chan_boot(uint16 chsa, DEVICE *dptr); +t_stat chan_set_devs(); +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); +int16 post_csw(CHANP *chp, uint32 rstat); /* FIFO support */ /* These are FIFO queues which return an error when full. @@ -188,7 +195,7 @@ int32 FIFO_Num(uint16 chsa) } /* calc entries */ num = (dibp->chan_fifo_in - dibp->chan_fifo_out + FIFO_SIZE) % FIFO_SIZE; - return (num>1); /* two words/entry */ + return (num>>1); /*GT*/ /* two words/entry */ } /* add an entry to the RDYQ */ @@ -328,72 +335,72 @@ uint32 find_int_icb(uint16 chsa) /* Find unit pointer for given device (ch/sa) */ UNIT *find_unit_ptr(uint16 chsa) { - struct dib *dibp; /* DIB pointer */ - UNIT *uptr; /* UNIT pointer */ + struct dib *dibp; /* DIB pointer */ + UNIT *uptr; /* UNIT pointer */ int i; - dibp = dib_unit[chsa]; /* get DIB pointer from device address */ - if (dibp == 0) { /* if zero, not defined on system */ + 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 */ + 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 */ + uptr = dibp->units; /* get the pointer to the units on this channel */ + if (uptr == 0) { /* if zero, no devices defined on system */ sim_debug(DEBUG_EXP, &cpu_dev, "find_unit_ptr ERR chsa %04x uptr %p\n", chsa, uptr); - return NULL; /* tell caller */ + 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? */ - return uptr; /* return the pointer */ + for (i = 0; i < dibp->numunits; i++) { /* search through units to get a match */ + if (chsa == GET_UADDR(uptr->u3)) { /* does ch/sa match? */ + return uptr; /* return the pointer */ } - uptr++; /* next unit */ + 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 */ + return NULL; /* device not found on system */ } /* Find channel program pointer for given device (ch/sa) */ CHANP *find_chanp_ptr(uint16 chsa) { - struct dib *dibp; /* DIB pointer */ - UNIT *uptr; /* UNIT pointer */ - CHANP *chp; /* CHANP pointer */ + struct dib *dibp; /* DIB pointer */ + UNIT *uptr; /* UNIT pointer */ + CHANP *chp; /* CHANP pointer */ int i; - dibp = dib_unit[chsa]; /* get DIB pointer from unit address */ - if (dibp == 0) { /* if zero, not defined on system */ + dibp = dib_unit[chsa]; /* get DIB pointer from unit address */ + if (dibp == 0) { /* if zero, not defined on system */ sim_debug(DEBUG_EXP, &cpu_dev, "find_chanp_ptr ERR chsa %04x dibp %p\n", chsa, dibp); - return NULL; /* tell caller */ + 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 */ + 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 */ + uptr = dibp->units; /* get the pointer to the units on this channel */ + if (uptr == 0) { /* if zero, no devices defined on system */ sim_debug(DEBUG_EXP, &cpu_dev, "find_chanp_ptr ERR chsa %04x uptr %p\n", chsa, uptr); - return NULL; /* tell caller */ + 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? */ - return chp; /* return the pointer */ + for (i = 0; i < dibp->numunits; i++) { /* search through units to get a match */ + if (chsa == GET_UADDR(uptr->u3)) { /* does ch/sa match? */ + return chp; /* return the pointer */ } - uptr++; /* next UNIT */ - chp++; /* next CHANP */ + 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 */ + return NULL; /* device not found on system */ } /* Read a full word into memory. @@ -402,16 +409,16 @@ CHANP *find_chanp_ptr(uint16 chsa) */ int readfull(CHANP *chp, uint32 maddr, uint32 *word) { - maddr &= MASK24; /* mask addr to 24 bits */ - if (!MEM_ADDR_OK(maddr)) { /* see if mem addr >= MEMSIZE */ - chp->chan_status |= STATUS_PCHK; /* program check error */ + maddr &= MASK24; /* mask addr to 24 bits */ + if (!MEM_ADDR_OK(maddr)) { /* see if mem addr >= MEMSIZE */ + chp->chan_status |= STATUS_PCHK; /* program check error */ sim_debug(DEBUG_EXP, &cpu_dev, "readfull read %08x from addr %08x ERROR\n", *word, maddr); - return 1; /* show we have error */ + return 1; /* show we have error */ } - *word = RMW(maddr); /* get 1 word */ + *word = RMW(maddr); /* get 1 word */ sim_debug(DEBUG_XIO, &cpu_dev, "READFULL read %08x from addr %08x\n", *word, maddr); - return 0; /* return OK */ + return 0; /* return OK */ } /* Read a byte into the channel buffer. @@ -420,17 +427,17 @@ int readfull(CHANP *chp, uint32 maddr, uint32 *word) */ int readbuff(CHANP *chp) { - uint32 addr = chp->ccw_addr; /* channel buffer address */ + uint32 addr = chp->ccw_addr; /* channel buffer address */ - if (!MEM_ADDR_OK(addr & MASK24)) { /* see if memory address invalid */ - chp->chan_status |= STATUS_PCHK; /* bad, program check */ + if (!MEM_ADDR_OK(addr & MASK24)) { /* see if memory address invalid */ + chp->chan_status |= STATUS_PCHK; /* bad, program check */ 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 & busy */ - return 1; /* done, with error */ + chp->chan_byte = BUFF_CHNEND; /* force channel end & busy */ + return 1; /* done, with error */ } - chp->chan_buf = RMB(addr&MASK24); /* get 1 byte */ + chp->chan_buf = RMB(addr&MASK24); /* get 1 byte */ return 0; } @@ -466,7 +473,6 @@ int32 load_ccw(CHANP *chp, int32 tic_ok) uint32 word1 = 0; uint32 word2 = 0; int docmd = 0; -//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; @@ -507,7 +513,7 @@ 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 +#ifdef FOR_DEBUG if ((word2>>16) & (FLAG_CC|FLAG_DC)) { uint32 word3 = 0; uint32 word4 = 0; @@ -551,7 +557,6 @@ loop: 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*/ -//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? */ @@ -563,20 +568,9 @@ loop: "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 - /* LPR sends CC cmd only without data addr/count */ - /* Check invalid count */ - if ((chp->ccw_count == 0) && (chp->ccw_addr != 0)) { /* see if byte count is zero */ - chp->chan_status |= STATUS_PCHK; /* program check if it is */ - irq_pend = 1; /* status pending int */ - return 1; /* error return */ - } -#endif - if (docmd) { /* see if we need to process a command */ DIB *dibp = dib_unit[chp->chan_dev]; /* get the DIB 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 */ @@ -590,11 +584,6 @@ loop: /* call the device startcmd function to process the current command */ /* just replace device status bits */ devstat = dibp->start_cmd(uptr, chan, chp->ccw_cmd); -// 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, @@ -607,22 +596,16 @@ loop: chp->chan_status |= STATUS_CEND; /* channel end status */ chp->ccw_flags = 0; /* no flags */ chp->ccw_cmd = 0; /* stop IOCD processing */ -////XXX irq_pend = 1; /* int coming */ sim_debug(DEBUG_EXP, &cpu_dev, "load_ccw bad status chan %04x status %04x\n", chan, chp->chan_status); -#ifndef XXX chp->chan_byte = BUFF_NEXT; /* have main pick us up */ RDYQ_Put(chp->chan_dev); /* queue us up */ sim_debug(DEBUG_EXP, &cpu_dev, "load_ccw continue wait chsa %04x status %08x\n", chp->chan_dev, chp->chan_status); -//// irq_pend = 1; /* show pending int */ -#else - return 1; /* error return */ -#endif } -#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 */ @@ -633,16 +616,6 @@ loop: "load_ccw @%06x FIFO #%1x cmd complete chan %04x status %04x count %04x\n", chp->chan_caw, FIFO_Num(chsa), chan, chp->chan_status, chp->ccw_count); } -#else - /* we have good status */ - if (chp->chan_status & (STATUS_DEND|STATUS_CEND)) { - chp->chan_byte = BUFF_NEXT; /* have main pick us up */ - RDYQ_Put(chp->chan_dev); /* queue us up */ - sim_debug(DEBUG_EXP, &cpu_dev, - "load_ccw good status chan %04x status %04x\n", - chan, chp->chan_status); - } -#endif } /* the device processor return OK (0), so wait for I/O to complete */ /* nothing happening, so return */ @@ -669,8 +642,6 @@ int chan_read_byte(uint16 chsa, uint8 *data) if (chp->ccw_count == 0) { /* see if more data required */ if ((chp->ccw_flags & FLAG_DC) == 0) { /* see if Data Chain */ -//040120 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", @@ -712,8 +683,7 @@ int test_write_byte_end(uint16 chsa) return 1; /* return done */ if (chp->ccw_count == 0) { if ((chp->ccw_flags & FLAG_DC) == 0) { /* see if we have data chaining */ -//040120 chp->chan_status |= STATUS_CEND; /* no, end of data */ -/*BACK*/ chp->chan_status |= STATUS_CEND; /* no, end of data */ + chp->chan_status |= STATUS_CEND; /* no, end of data */ chp->chan_byte = BUFF_CHNEND; /* thats all the data we want */ return 1; /* return done */ } @@ -752,8 +722,7 @@ int chan_write_byte(uint16 chsa, uint8 *data) if ((chp->ccw_flags & FLAG_DC) == 0) { /* see if we have data chaining */ sim_debug(DEBUG_EXP, &cpu_dev, "chan_write_byte no DC ccw_flags %04x\n", chp->ccw_flags); -//040120 chp->chan_status |= STATUS_CEND; /* no, end of data */ -/*BACK*/ chp->chan_status |= STATUS_CEND; /* no, end of data */ + chp->chan_status |= STATUS_CEND; /* no, end of data */ chp->chan_byte = BUFF_CHNEND; /* thats all the data we want */ return 1; /* return done error */ } else { @@ -775,7 +744,6 @@ int chan_write_byte(uint16 chsa, uint8 *data) /* see if we want to skip writing data to memory */ if (chp->ccw_flags & FLAG_SKIP) { chp->ccw_count--; /* decrement skip count */ -//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 */ @@ -788,16 +756,8 @@ int chan_write_byte(uint16 chsa, uint8 *data) chp->chan_buf = *data; /* get data byte */ if (writebuff(chp)) /* write the byte */ return 1; -#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 previous address */ @@ -826,7 +786,13 @@ void set_devattn(uint16 chsa, uint16 flags) { CHANP *chp = find_chanp_ptr(chsa); /* get channel prog pointer */ - sim_debug(DEBUG_EXP, &cpu_dev, "set_devattn chsa %04x, flags %04x\n", chsa, flags); + if (chp == NULL) { + /* can not do anything, so just return */ + sim_debug(DEBUG_EXP, &cpu_dev, "set_devattn chsa %04x, flags %04x\n", chsa, flags); + fprintf(stdout, "set_devattn chsa %04x invalid configured device\n", chsa); + fflush(stdout); + return; + } if (chp->chan_dev == chsa && (chp->chan_status & STATUS_CEND) != 0 && (flags & SNS_DEVEND) != 0) { chp->chan_status |= ((uint16)flags); @@ -843,7 +809,6 @@ 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); -//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 */ @@ -870,17 +835,10 @@ 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); -//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 if ((chp->chan_status & STATUS_LENGTH) && ((chp->chan_status & STATUS_DEND) == 0)) chp->chan_status &= ~STATUS_LENGTH; -#else - if ((chp->chan_status & FLAG_SLI) && ((chp->chan_status & STATUS_DEND) == 0)) - chp->chan_status &= ~FLAG_SLI; -#endif /* no flags for attention status */ if (flags & (SNS_ATTN|SNS_UNITCHK|SNS_UNITEXP)) { @@ -893,7 +851,6 @@ void chan_end(uint16 chsa, uint16 flags) { /* test for device or controller end */ if (chp->chan_status & (STATUS_DEND|STATUS_CEND)) { -//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 */ @@ -903,8 +860,6 @@ void chan_end(uint16 chsa, uint16 flags) { chp->ccw_flags = 0; /* no flags */ } } -//040120chp->chan_byte = BUFF_DONE; /* 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", @@ -1022,7 +977,6 @@ void store_csw(CHANP *chp) 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 */ } @@ -1054,11 +1008,9 @@ 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 */ -//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; -//Z uint32 incha; DEVICE *dptr; /* DEVICE pointer */ sim_debug(DEBUG_XIO, &cpu_dev, "checkxio entry chsa %04x\n", chsa); @@ -1066,13 +1018,10 @@ t_stat checkxio(uint16 chsa, uint32 *status) { 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: @@ -1111,7 +1060,6 @@ nothere: #endif /* check for a Command or data chain operation in progresss */ -//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 byte %02x\n", @@ -1124,11 +1072,9 @@ nothere: /* 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 */ } @@ -1166,7 +1112,6 @@ t_stat startxio(uint16 chsa, uint32 *status) { 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 */ incha = RMW(incha); /* 224 word buffer is inch addr */ dibp = dib_chan[chan]; /* get the channel DIB pointer */ @@ -1182,16 +1127,15 @@ t_stat startxio(uint16 chsa, uint32 *status) { dibp = dib_unit[chsa]; /* get the DIB pointer */ chp = find_chanp_ptr(chsa); /* find the 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 */ + if (dibp == 0 || chp == 0) { /* if no dib or channel ptr, CC3 return */ *status = CC3BIT; /* not found, so CC3 */ sim_debug(DEBUG_EXP, &cpu_dev, "startxio chsa %04x device not present, CC3 returned\n", chsa); return SCPE_OK; /* not found, CC3 */ } + uptr = chp->unitptr; /* get the unit ptr */ if ((uptr->flags & UNIT_ATTABLE) && ((uptr->flags & UNIT_ATT) == 0)) { /* is unit attached? */ sim_debug(DEBUG_EXP, &cpu_dev, "startxio chsa %04x device not present, CC3 returned flags %08x\n", chsa, uptr->flags); @@ -1200,7 +1144,7 @@ t_stat startxio(uint16 chsa, uint32 *status) { } inta = find_int_lev(chsa); /* Interrupt Level for channel */ -#ifndef NONO +#ifndef FOR_DEBUG if ((INTS[inta]&INTS_ACT) || (SPAD[inta+0x80]&SINT_ACT)) { /* look for level active */ /* just output a warning */ sim_debug(DEBUG_XIO, &cpu_dev, @@ -1212,7 +1156,6 @@ t_stat startxio(uint16 chsa, uint32 *status) { #endif /* check for a Command or data chain operation in progresss */ -//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); @@ -1227,7 +1170,7 @@ t_stat startxio(uint16 chsa, uint32 *status) { iocla = RMW(chan_icb+16); /* iocla is in wd 4 of ICB */ incha = chp->chan_inch_addr; /* get inch address */ -#ifdef LEAVE_IT +#ifdef LEAVE_IT_ALONE /* now store the inch status address into word 5 of the ICB for the channel */ WMW(chan_icb+20, incha); /* post inch addr in ICB+5w */ #endif @@ -1286,7 +1229,6 @@ t_stat testxio(uint16 chsa, uint32 *status) { /* test XIO */ 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; @@ -1294,17 +1236,15 @@ 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 */ -//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 */ + if (dibp == 0 || chp == 0) { /* if no dib or channel ptr, CC3 return */ *status = CC3BIT; /* not found, so CC3 */ sim_debug(DEBUG_EXP, &cpu_dev, "testxio chsa %04x device not present, CC3 returned\n", chsa); goto tioret; /* not found, CC3 */ } + uptr = chp->unitptr; /* get the unit ptr */ if ((uptr->flags & UNIT_ATTABLE) && ((uptr->flags & UNIT_ATT) == 0)) { /* is unit attached? */ *status = CC3BIT; /* not attached, so error CC3 */ sim_debug(DEBUG_EXP, &cpu_dev, @@ -1313,7 +1253,6 @@ t_stat testxio(uint16 chsa, uint32 *status) { /* test XIO */ } /* check for a Command or data chain operation in progresss */ -//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); @@ -1341,7 +1280,6 @@ 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", @@ -1349,19 +1287,6 @@ t_stat testxio(uint16 chsa, uint32 *status) { /* test XIO */ INTS[inta] &= ~INTS_REQ; /* clear any level request */ goto tioret; /* CC2 and OK */ } -#ifdef TESTING_032020_XXX_UNDO_041220 - if ((CPUSTATUS & 0x80) != 0) { /* are interrupts blocked */ -// uint32 chan_icb = find_int_icb(chsa); /* get icb address */ -// tempa = chp->chan_inch_addr; /* get inch status buffer address */ - if (incha && (incha & BIT1)) { /* see if status was posted */ - *status = CC2BIT; /* status stored from SIO, so CC2 */ - sim_debug(DEBUG_XIO, &cpu_dev, - "testxio ECHO status stored incha %06x chsa %04x sw1 %08x sw2 %08x\n", - incha, chsa, RMW(incha), RMW(incha+4)); - goto tioret; /* CC2 and OK */ - } - } -#endif /* nothing going on, so say all OK */ *status = CC1BIT; /* request accepted, no status, so CC1 */ tioret: @@ -1384,16 +1309,15 @@ 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 */ -//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 */ + if (dibp == 0 || chp == 0) { /* if no dib or channel ptr, CC3 return */ *status = CC3BIT; /* not found, so CC3 */ sim_debug(DEBUG_EXP, &cpu_dev, "stopxio test 1 chsa %04x device not present, CC3 returned\n", chsa); return SCPE_OK; /* not found CC3 */ } + uptr = chp->unitptr; /* get the unit ptr */ if ((uptr->flags & UNIT_ATTABLE) && ((uptr->flags & UNIT_ATT) == 0)) { /* is unit attached? */ *status = CC3BIT; /* not attached, so error CC3 */ sim_debug(DEBUG_EXP, &cpu_dev, @@ -1411,7 +1335,6 @@ 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 */ -//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 */ @@ -1438,19 +1361,17 @@ 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 */ -//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 */ + if (dibp == 0 || chp == 0) { /* if no dib or channel ptr, CC3 return */ *status = CC3BIT; /* not found, so CC3 */ sim_debug(DEBUG_EXP, &cpu_dev, "rschnlxio test 1 chsa %04x device not present, CC3 returned\n", chsa); return SCPE_OK; /* not found CC3 */ } + uptr = chp->unitptr; /* get the unit ptr */ if ((uptr->flags & UNIT_ATTABLE) && ((uptr->flags & UNIT_ATT) == 0)) { /* is unit attached? */ *status = CC3BIT; /* not attached, so error CC3 */ sim_debug(DEBUG_EXP, &cpu_dev, @@ -1499,9 +1420,7 @@ t_stat haltxio(uint16 lchsa, uint32 *status) { /* halt XIO */ uint32 iocla; /* I/O channel IOCL address int ICB */ uint32 inta, spadent, tempa; uint16 chsa; -// CHANP *chp, *pchp; /* Channel prog pointers */ CHANP *chp; /* Channel prog pointers */ -// uint32 sw1=0, sw2=0; /* status word 1 & 2 */ /* get the device entry for the logical channel in SPAD */ spadent = SPAD[chan]; /* get spad device entry for logical channel */ @@ -1509,9 +1428,7 @@ t_stat haltxio(uint16 lchsa, uint32 *status) { /* halt XIO */ chsa = (chan << 8) | (lchsa & 0xff); /* merge sa to real channel */ dibp = dib_unit[chsa]; /* get the device DIB pointer */ chp = find_chanp_ptr(chsa); /* find the chanp pointer */ -//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); if (dibp == 0 || uptr == 0) { /* if no dib or unit ptr, CC3 on return */ @@ -1543,7 +1460,6 @@ 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); -//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 */ @@ -1551,16 +1467,12 @@ t_stat haltxio(uint16 lchsa, uint32 *status) { /* halt XIO */ 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); -//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 */ -//ZZ goto hioret; /* CC1 and OK */ goto hiogret; /* CC1 and OK */ } /* the channel is busy, so process */ -//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 */ @@ -1577,7 +1489,6 @@ 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 */ /* 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 */ @@ -1589,21 +1500,9 @@ t_stat haltxio(uint16 lchsa, uint32 *status) { /* halt XIO */ } } /* 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, - "$$$ HALTXIO FIFO #%1x good return chsa %04x cmd %02x ccw_flags %04x status %04x\n", - FIFO_Num(chsa), chsa, chp->ccw_cmd, chp->ccw_flags, *status); - *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 */ -//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); @@ -1612,18 +1511,13 @@ 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 */ -//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 */ /* 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 */ INTS[inta] &= ~INTS_REQ; /* clear any level request */ *status = CC2BIT; /* status stored from SIO, so CC2 */ goto hioret; /* just return */ @@ -1680,7 +1574,6 @@ 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 */ -//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); @@ -1739,6 +1632,24 @@ t_stat chan_boot(uint16 chsa, DEVICE *dptr) { if (dibp->chan_prg == NULL) /* must have channel information for each device */ return SCPE_IOERR; /* error */ chp = find_chanp_ptr(chsa); /* find the chanp pointer */ + if (chp == 0) /* if no channel, error */ + return SCPE_IOERR; /* error */ + + /* make sure there is an IOP/MFP configured at 7e00 on system */ + if (dib_chan[0x7e] == NULL) { + sim_debug(DEBUG_CMD, dptr, + "ERROR===ERROR\nIOP/MFP device 0x7e00 not configured on system, aborting\n"); + printf("ERROR===ERROR\nIOP/MFP device 0x7e00 not configured on system, aborting\n"); + return SCPE_UNATT; /* error */ + } + + /* make sure there is an IOP/MFP console configured at 7efc/7efd on system */ + if ((dib_unit[0x7efc] == NULL) || (dib_unit[0x7efd] == NULL)) { + sim_debug(DEBUG_CMD, dptr, + "ERROR===ERROR\nCON device 0x7efc/0x7ecd not configured on system, aborting\n"); + printf("ERROR===ERROR\nCON device 0x7efc/0x7efd not configured on system, aborting\n"); + return SCPE_UNATT; /* error */ + } chp->chan_status = 0; /* clear the channel status */ chp->chan_dev = chsa; /* save our address (ch/sa) */ @@ -1758,7 +1669,6 @@ 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 */ -//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 */ @@ -1781,7 +1691,6 @@ uint32 cont_chan(uint16 chsa) "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); @@ -1800,7 +1709,6 @@ uint32 cont_chan(uint16 chsa) 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 */ @@ -1809,7 +1717,6 @@ uint32 cont_chan(uint16 chsa) 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 */ } /* we get here when nothing left to do and status is stored */ @@ -1826,14 +1733,16 @@ uint32 cont_chan(uint16 chsa) interrupt pending. Return icb address and interrupt level */ uint32 scan_chan(uint32 *ilev) { -// int i,j; int i; +#ifndef GEERT_UNDO + void CatchSig(); + void ReportIRQs(); +#endif uint32 chsa; /* No device */ uint32 chan; /* channel num 0-7f */ uint32 tempa; /* icb address */ uint32 chan_ivl; /* int level table address */ -// uint32 chan_icb; /* Interrupt level context block address */ - uint32 chan_icba; /* int level context block address */ + uint32 chan_icba; /* Interrupt level context block address */ CHANP *chp; /* channel prog pointer */ DIB *dibp; /* DIB pointer */ uint32 sw1, sw2; /* status words */ @@ -1863,6 +1772,18 @@ uint32 scan_chan(uint32 *ilev) { return 0; /* not ready, return */ } +#ifndef GEERT_UNDO + ScanCycles++; + + /* install signal handler after say 100 ScanCycles */ + if (ScanCycles == 100) + signal(SIGQUIT, CatchSig); + + if (DoNextCycles) { + ReportIRQs(); + DoNextCycles--; + } +#endif /* see if we are able to look for ints */ if (irq_pend == 0) /* pending int? */ return 0; /* no, done */ @@ -1881,8 +1802,9 @@ uint32 scan_chan(uint32 *ilev) { FIFO_Num(SPAD[i+0x80] & 0x7f00), i, SPAD[i+0x80], INTS[i]); return 0; /* this level active, so stop looking */ } -/*0418*/if ((INTS[i] & INTS_ENAB) == 0) /* ints must be enabled */ + if ((INTS[i] & INTS_ENAB) == 0) /* ints must be enabled */ continue; /* skip this one */ + /* see if there is pending status for this channel */ /* if there is and the level is not requesting, do it */ /* get the device entry for the logical channel in SPAD */ @@ -1893,10 +1815,9 @@ uint32 scan_chan(uint32 *ilev) { 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 = dibp->chan_fifo[dibp->chan_fifo_out]; /* get SW1 of FIFO entry */ + chsa = chan | (tempa >> 24); /* find device address for requesting chan prog */ + 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 */ @@ -1904,28 +1825,31 @@ uint32 scan_chan(uint32 *ilev) { sim_debug(DEBUG_IRQ, &cpu_dev, "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)); + /* device 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 */ - *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 */ + /* 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 */ @@ -1938,15 +1862,12 @@ uint32 scan_chan(uint32 *ilev) { "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 + return(chan_icba); /* return ICB address */ } 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 */ /* that is enabled */ if (((INTS[i] & INTS_ENAB) && (INTS[i] & INTS_REQ)) || @@ -1956,6 +1877,7 @@ uint32 scan_chan(uint32 *ilev) { 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 */ @@ -1969,35 +1891,11 @@ uint32 scan_chan(uint32 *ilev) { *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 */ - /* 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 */ - /* 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 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 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]); - } + + 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]); + return(chan_icba); /* return ICB address */ } } @@ -2019,6 +1917,7 @@ DEVICE *get_dev(UNIT *uptr) return NULL; if (uptr->dptr) /* get device pointer from unit */ return uptr->dptr; /* return valid pointer */ + /* the device pointer in the unit is not set up, do it now */ /* This should never happed as the pointer is setup in first reset call */ for (i = 0; (dptr = sim_devices[i]) != NULL; i++) { /* do all devices */ @@ -2166,7 +2065,6 @@ t_stat set_dev_addr(UNIT *uptr, int32 val, CONST char *cptr, void *desc) { int i; /* temp */ int chsa; /* dev addr */ -// dptr = uptr->dptr /* get device pointer from unit */ if (cptr == NULL) /* is there a UNIT name specified */ return SCPE_ARG; /* no, arg error */ if (uptr == NULL) /* is there a UNIT pointer */ @@ -2189,6 +2087,7 @@ t_stat set_dev_addr(UNIT *uptr, int32 val, CONST char *cptr, void *desc) { /* change all the unit addresses with the new channel, but keep sub address */ /* Clear out existing entries for all units on this device */ tuptr = dptr->units; /* get pointer to units defined for this device */ + /* loop through all units for this device */ for (i = 0; i < dibp->numunits; i++) { chsa = GET_UADDR(tuptr->u3); /* get old chsa for this unit */ @@ -2205,6 +2104,7 @@ t_stat set_dev_addr(UNIT *uptr, int32 val, CONST char *cptr, void *desc) { return SCPE_OK; } +/* display channel/sub-address for device */ t_stat show_dev_addr(FILE *st, UNIT *uptr, int32 v, CONST void *desc) { DEVICE *dptr; int chsa; @@ -2218,3 +2118,63 @@ t_stat show_dev_addr(FILE *st, UNIT *uptr, int32 v, CONST void *desc) { fprintf(st, "CHAN/SA %04x", chsa); /* display channel/subaddress */ return SCPE_OK; /* we done */ } + +#ifndef GEERT_UNDO +void CatchSig() { + void ReportIRQs(); + + /* re-install signal handler */ + signal(SIGQUIT, CatchSig); + + sim_debug(DEBUG_IRQ, &cpu_dev, "SIG[%d] CPUSTATUS=%08x\n", + ScanCycles, CPUSTATUS); + + ReportIRQs(); + DoNextCycles = 20; +} + +void ReportIRQs() { + int i, irqs = 0; + int levels[5]; + char *s; + + for (i=0; i<112; i++) + if (INTS[i] & INTS_REQ) { + if (irqs < 5) + levels[irqs] = i; + irqs++; + } + + if (CPUSTATUS & 0x80) + s = " BLOCKED"; + else + s = ""; + + switch (irqs) { + case 1: + sim_debug(DEBUG_IRQ, &cpu_dev, + "SIG[%d]%s irq_pend=%d, ACT=%d: %x\n", + ScanCycles, s, irq_pend, irqs, levels[0]); + break; + case 2: + sim_debug(DEBUG_IRQ, &cpu_dev, + "SIG[%d]%s irq_pend=%d, ACT=%d: %x, %x\n", + ScanCycles, s, irq_pend, irqs, levels[0], levels[1]); + break; + case 3: + sim_debug(DEBUG_IRQ, &cpu_dev, + "SIG[%d]%s irq_pend=%d, ACT=%d: %x, %x, %x\n", + ScanCycles, s, irq_pend, irqs, levels[0], levels[1], levels[2]); + break; + case 4: + sim_debug(DEBUG_IRQ, &cpu_dev, + "SIG[%d]%s irq_pend=%d, ACT=%d: %x, %x, %x, %x\n", + ScanCycles, s, irq_pend, irqs, levels[0], levels[1], levels[2], levels[3]); + break; + default: + sim_debug(DEBUG_IRQ, &cpu_dev, + "SIG[%d]%s irq_pend=%d, ACT=%d\n", + ScanCycles, s, irq_pend, irqs); + } +} +#endif diff --git a/SEL32/sel32_clk.c b/SEL32/sel32_clk.c index a14b964..1f743e8 100644 --- a/SEL32/sel32_clk.c +++ b/SEL32/sel32_clk.c @@ -45,7 +45,7 @@ t_stat rtc_show_freq (FILE *st, UNIT *uptr, int32 val, CONST void *desc); t_stat rtc_help(FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, CONST char *cptr); const char *rtc_desc(DEVICE *dptr); -extern int irq_pend; /* go scan for pending int or I/O */ +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 */ @@ -57,7 +57,6 @@ int32 rtc_tps = 60; /* rtc ticks/sec */ int32 rtc_lvl = 0x18; /* rtc interrupt level */ /* Clock data structures - rtc_dev RTC device descriptor rtc_unit RTC unit rtc_reg RTC register list @@ -94,7 +93,6 @@ DEVICE rtc_dev = { 1, 8, 8, 1, 8, 8, NULL, NULL, &rtc_reset, /* examine, deposit, reset */ NULL, NULL, NULL, /* boot, attach, detach */ -// NULL, 0, 0, NULL, /* dib, dev flags, debug flags, debug */ NULL, DEV_DEBUG|DEV_DISABLE, 0, dev_debug, /* dib, dev flags, debug flags, debug */ NULL, NULL, &rtc_help, /* ?, ?, help */ NULL, NULL, &rtc_desc, /* ?, ?, description */ @@ -113,41 +111,29 @@ uint32 grtime = 0; /* service clock signal from simulator */ t_stat rtc_srv (UNIT *uptr) { -#ifdef STOP_CLOCK_INTS_FOR_DEXP_TEST + int32 temp; +#ifdef STOP_CLOCK_INTS_FOR_DEXP_TEST_DEBUGGING /* stop clock interrupts for dexp debugging */ rtc_pie = 0; #endif /* id clock sisabled, do not do interrupts */ if (((uptr->flags & DEV_DIS) == 0) && rtc_pie) { -// if (rtc_pie) { /* set pulse intr */ time_t result = time(NULL); sim_debug(DEBUG_CMD, &rtc_dev, "RT Clock int time %08x\n", (uint32)result); -#ifdef DO_TIME - time_t result = time(NULL); - uint32 tms = sim_os_msec(); - uint32 tus = sim_grtime(); - if (lastms != 0) - fprintf(stderr, "Clock time %08x ms %d val %x\r\n", (uint32)result, tms-lastms, tms); -// fprintf(stderr, "Clock time %08x ms %d us %d\r\n", (uint32)result, tms-lastms, tus-grtime); - lastms = tms; - grtime = tus; -#endif if (((INTS[rtc_lvl] & INTS_ENAB) || /* make sure enabled */ (SPAD[rtc_lvl+0x80] & SINT_ENAB)) && /* in spad too */ (((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 */ + /* HACK for console I/O stopping */ + /* This reduces the number of console I/O stopping errors */ + /* need tp find real cause of I/O stopping on clock interrupt */ if ((outbusy==0) && (inbusy==0)) /* skip interrupt if con I/O in busy wait */ - INTS[rtc_lvl] |= INTS_REQ; /* request the interrupt */ + INTS[rtc_lvl] |= INTS_REQ; /* request the interrupt */ irq_pend = 1; /* make sure we scan for int */ } } -#define 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 */ -#endif - sim_activate_after (&rtc_unit, 1000000/rtc_tps);/* reactivate 16666 tics / sec */ + temp = sim_rtcn_calb(rtc_tps, TMR_RTC); /* timer 0 for RTC */ + sim_activate_after(&rtc_unit, 1000000/rtc_tps); /* reactivate 16666 tics / sec */ return SCPE_OK; } @@ -157,7 +143,6 @@ t_stat rtc_srv (UNIT *uptr) /* level = interrupt level */ void rtc_setup(uint32 ss, uint32 level) { -// uint32 val = SPAD[level+0x80]; /* get SPAD value for interrupt vector */ uint32 addr = SPAD[0xf1] + (level<<2); /* vector address in SPAD */ rtc_lvl = level; /* save the interrupt level */ @@ -169,16 +154,11 @@ void rtc_setup(uint32 ss, uint32 level) sim_debug(DEBUG_CMD, &rtc_dev, "RT Clock setup enable int %02x rtc_pie %01x ss %01x\n", rtc_lvl, rtc_pie, ss); -#ifdef DO_DYNAMIC_DEBUG - /* start debugging */ - cpu_dev.dctrl |= (DEBUG_INST | DEBUG_CMD | DEBUG_EXP | DEBUG_IRQ | DEBUG_TRAP); -#endif } else { INTS[level] &= ~INTS_ENAB; /* make sure disabled */ SPAD[level+0x80] &= ~SINT_ENAB; /* in spad too */ -// INTS[level] &= ~INTS_REQ; /* make sure request not requesting */ -/*@41*/ INTS[level] &= ~INTS_ACT; /* make sure request not active */ -/*@41*/ SPAD[level+0x80] &= ~SINT_ACT; /* in spad too */ + INTS[level] &= ~INTS_ACT; /* make sure request not active */ + SPAD[level+0x80] &= ~SINT_ACT; /* in spad too */ sim_debug(DEBUG_CMD, &rtc_dev, "RT Clock setup disable int %02x rtc_pie %01x ss %01x\n", rtc_lvl, rtc_pie, ss); @@ -191,10 +171,6 @@ t_stat rtc_reset(DEVICE *dptr) { rtc_pie = 0; /* disable pulse */ /* initialize clock calibration */ -#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); -#endif sim_activate (&rtc_unit, rtc_unit.wait); /* activate unit */ return SCPE_OK; } @@ -260,20 +236,15 @@ t_stat itm_help(FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, CONST char *cptr const char *itm_desc(DEVICE *dptr); /* Clock data structures - itm_dev Interval Timer ITM device descriptor itm_unit Interval Timer ITM unit itm_reg Interval Timer ITM register list */ -#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 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 -UNIT itm_unit = { UDATA (&itm_srv, UNIT_IDLE, 0), 26042, UNIT_ADDR(0x7F04)}; -#endif REG itm_reg[] = { { FLDATA (PIE, itm_pie, 0) }, @@ -298,7 +269,6 @@ DEVICE itm_dev = { 1, 8, 8, 1, 8, 8, NULL, NULL, &itm_reset, /* examine, deposit, reset */ NULL, NULL, NULL, /* boot, attach, detach */ -// NULL, 0, 0, NULL, /* dib, ?, ?, debug */ NULL, DEV_DEBUG, 0, dev_debug, /* dib, dev flags, debug flags, debug */ NULL, NULL, &itm_help, /* ?, ?, help */ NULL, NULL, &itm_desc, /* ?, ?, description */ @@ -336,15 +306,14 @@ t_stat itm_srv (UNIT *uptr) /* restart timer with value from user */ if (itm_src) /* use specified src freq */ sim_activate_after_abs_d(&itm_unit, ((double)itm_cnt*350000)/rtc_tps); -// sim_activate_after_abs_d(&itm_unit, ((double)itm_cnt*400000)/rtc_tps); -// sim_activate_after_abs_d(&itm_unit, ((double)itm_cnt*1000000)/rtc_tps); +//DIAG sim_activate_after_abs_d(&itm_unit, ((double)itm_cnt*400000)/rtc_tps); +//DIAG sim_activate_after_abs_d(&itm_unit, ((double)itm_cnt*1000000)/rtc_tps); else sim_activate_after_abs_d(&itm_unit, ((double)itm_cnt*itm_tick_size_x_100)/100.0); itm_run = 1; /* show timer running */ itm_load = itm_cnt; /* save loaded value */ itm_strt = 0; /* no negative start time */ } else { -// int32 cnt = 26042*1000; /* 0x65ba TRY 1,000,000/38.4 10 secs */ int32 cnt = itm_big; /* 0x65ba TRY 1,000,000/38.4 10 secs */ itm_strt = cnt; /* get negative start time */ sim_debug(DEBUG_CMD, &itm_dev, @@ -422,12 +391,6 @@ int32 itm_rdwr(uint32 cmd, int32 cnt, uint32 level) case 0x39: /* load timer with new value and start lo rate */ case 0x3a: /* load timer with new value and start hi rate */ case 0x3b: /* load timer with new value and start lo rate */ -#ifdef DO_DYNAMIC_DEBUG - if (itm_cmd == 0x38) - /* start debugging */ - cpu_dev.dctrl |= (DEBUG_INST | DEBUG_CMD | DEBUG_EXP | DEBUG_IRQ | DEBUG_TRAP); -#endif -// sim_activate_after (&rtc_unit, 1000000/rtc_tps);/* reactivate 16666 tics / sec */ if (itm_run) /* if we were running stop timer */ sim_cancel (&itm_unit); /* cancel timer */ itm_run = 0; /* stop timer running */ @@ -436,7 +399,6 @@ int32 itm_rdwr(uint32 cmd, int32 cnt, uint32 level) /* if bits 30-31 == 20, use RTC freq */ itm_src = (cmd>>1)&1; /* set src */ if (itm_src) /* use specified src freq */ -// sim_activate_after_abs_d(&itm_unit, ((double)cnt*400000)/rtc_tps); /* use clock frequency */ sim_activate_after_abs_d(&itm_unit, ((double)cnt*1000000)/rtc_tps); else @@ -476,10 +438,6 @@ int32 itm_rdwr(uint32 cmd, int32 cnt, uint32 level) } sim_cancel (&itm_unit); /* cancel timer */ } -// if (cmd & 0x40) { -// /* timer value already read into temp */ -// ; -// } if (cmd & 0x08) { /* use value from user to load timer */ temp = cnt; /* set user count */ @@ -489,7 +447,7 @@ int32 itm_rdwr(uint32 cmd, int32 cnt, uint32 level) /* if bits 30-31 == 20, use RTC freq */ itm_src = (cmd>>1)&1; /* set src */ if (itm_src) /* use specified src freq */ -// sim_activate_after_abs_d(&itm_unit, ((double)cnt*400000)/rtc_tps); +//DIAG sim_activate_after_abs_d(&itm_unit, ((double)cnt*400000)/rtc_tps); sim_activate_after_abs_d(&itm_unit, ((double)cnt*1000000)/rtc_tps); else sim_activate_after_abs_d(&itm_unit, ((double)cnt*itm_tick_size_x_100)/100.0); @@ -510,21 +468,17 @@ int32 itm_rdwr(uint32 cmd, int32 cnt, uint32 level) /* load timer with new value and start using RTC as source */ case 0x3e: /* load timer with new value and start RTC*/ sim_debug(DEBUG_CMD, &itm_dev, "Intv 0x%2x init value %08x (%d)\n", cmd, cnt, cnt); -//TRY if (itm_run) /* if we were running save curr cnt */ - sim_cancel (&itm_unit); /* cancel timer */ + sim_cancel (&itm_unit); /* cancel timer */ /* if bits 30-31 == 20, use RTC freq */ itm_src = (cmd>>1)&1; /* set src */ if (itm_src) /* use specified src freq */ sim_activate_after_abs_d(&itm_unit, ((double)cnt*700000)/rtc_tps); -// sim_activate_after_abs_d(&itm_unit, ((double)cnt*1000000)/rtc_tps); else sim_activate_after_abs_d(&itm_unit, ((double)cnt*itm_tick_size_x_100)/100.0); itm_run = 1; /* set timer running */ if (cmd & 0x04) /* do we reload on zero? */ itm_cnt = cnt; /* count reset value */ - else - itm_cnt = 0; /* no count reset value */ itm_strt = 0; /* not restarted neg */ itm_load = cnt; /* now loaded */ sim_debug(DEBUG_CMD, &itm_dev, "Intv 0x%02x return value %08x (%08d)\n", cmd, cnt, cnt); @@ -546,7 +500,6 @@ int32 itm_rdwr(uint32 cmd, int32 cnt, uint32 level) } sim_debug(DEBUG_CMD, &itm_dev, "Intv 0x40 return value %08x (%d)\n", temp, temp); return temp; -//TRIED return temp << 6; break; case 0x60: /* read and stop timer */ @@ -572,11 +525,6 @@ int32 itm_rdwr(uint32 cmd, int32 cnt, uint32 level) break; case 0x6a: /* read value & load new one */ -#ifdef DO_DYNAMIC_DEBUG -// if (itm_cmd == 0x31) - /* start debugging */ - cpu_dev.dctrl |= (DEBUG_INST | DEBUG_CMD | DEBUG_EXP | DEBUG_IRQ | DEBUG_TRAP); -#endif case 0x68: /* read value & load new one */ case 0x69: /* read value & load new one */ /* get timer value and load new value, do not start timer */ diff --git a/SEL32/sel32_com.c b/SEL32/sel32_com.c index 7d3cd49..bd56060 100644 --- a/SEL32/sel32_com.c +++ b/SEL32/sel32_com.c @@ -238,7 +238,6 @@ 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 */ }; //DIB com_dib = {NULL, com_startcmd, NULL, NULL, com_ini, com_unit, com_chp, COM_UNITS, 0x0f, 0x7e00, 0, 0, 0}; @@ -362,12 +361,6 @@ DEVICE coml_dev = { /* 8-line serial routines */ void coml_ini(UNIT *uptr, t_bool f) { -// int unit; -// uint16 chsa; - -// unit = uptr - coml_unit; /* unit # */ -// chsa = GET_UADDR(uptr->u3); /* get channel/sub-addr */ - /* maybe do someting here on master channel init */ uptr->u5 = SNS_RDY|SNS_ONLN; /* status is online & ready */ } @@ -402,7 +395,6 @@ uint16 com_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) uptr->u3 |= (0x7f & COM_MSK); /* save 0x7f as INCH cmd command */ uptr->u5 = SNS_RDY|SNS_ONLN; /* status is online & ready */ sim_activate(uptr, 20); /* start us up */ -// return SNS_CHNEND|SNS_DEVEND; /* all is well */ break; /* write commands must use address 8-f */ @@ -449,7 +441,6 @@ uint16 com_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) uptr->u3 &= LMASK; /* leave only chsa */ uptr->u3 |= (cmd & COM_MSK); /* save command */ sim_activate(uptr, 20); /* start us up */ -// return SNS_CHNEND|SNS_DEVEND; /* good return */ break; case COM_SNS: /* 0x04 */ /* Sense (8 bytes) */ @@ -459,68 +450,36 @@ uint16 com_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) /* value 5 is Data carrier detected n/u */ sim_debug(DEBUG_CMD, dptr, "com_startcmd %04x: unit %04x Cmd Sense %02x\n", chan, unit, uptr->u5); -/* Sense byte 0 */ -//#define SNS_CMDREJ 0x80000000 /* Command reject */ -//#define SNS_INTVENT 0x40000000 /* Unit intervention required (N/U) */ -//#define SNS_BOCHK 0x20000000 /* Bus out check (IOP parity error */ -//#define SNS_EQUIPCK 0x10000000 /* Equipment check (device error) */ -//#define SNS_DATACK 0x08000000 /* Data check */ -//#define SNS_OVERRN 0x04000000 /* Overrun (N/U) */ -//#define SNS_NUB01 0x02000000 /* Zero (N/U) */ -//#define SNS_NUB02 0x01000000 /* Zero (N/U) */ -// com_lstat[unit][0] |= (SNS_ASCIICD | SNS_SPCLCD|SNS_RING); /* set char detect status */ -// com_lstat[unit][0] |= (SNS_ASCIICD | SNS_SPCLCD); /* set char detect status */ -// com_lstat[unit][0] |= (SNS_RING); /* set char detect status */ + ch = (com_lstat[unit][0] >> 24) & 0xff; chan_write_byte(GET_UADDR(uptr->u3), &ch); /* write status */ -/* Sense byte 1 */ -//#define SNS_ASCIICD 0x00800000 /* ASCII control char detected interrupt */ -//#define SNS_SPCLCD 0x00400000 /* Special char detected interrupt */ -//#define SNS_ETX 0x00200000 /* ETX interrupt */ -//#define SNS_BREAK 0x00100000 /* X BREAK interrupt */ -//#define SNS_ACEFE 0x00080000 /* ACE framing error interrupt */ -//#define SNS_ACEPEI 0x00040000 /* ACE parity error interrupt */ -//#define SNS_ACEOVR 0x00020000 /* ACE overrun error interrupt */ -//#define SNS_RING 0x00010000 /* X Ring character interrupt */ + com_lstat[unit][0] |= (SNS_RING); /* set char detect status */ com_lstat[unit][0] |= (SNS_ASCIICD); /* set char detect status */ ch = (com_lstat[unit][0] >> 16) & 0xff; chan_write_byte(GET_UADDR(uptr->u3), &ch); /* write status */ -/* Sense byte 2 Modem status */ -//#define SNS_RLSDS 0x00008000 /* S Received line signal detect status */ -//#define SNS_RINGST 0x00004000 /* Ring indicator line status */ -//#define SNS_DSRS 0x00002000 /* C DSR Data set ready line status */ -//#define SNS_CTSS 0x00001000 /* C CTS Clear to send line status */ -//#define SNS_DELTA 0x00000800 /* BS Delta receive line signal detect failure interrupt */ -//#define SNS_MRING 0x00000400 /* X RI Modem ring interrupt */ -//#define SNS_DELDSR 0x00000200 /* BS Delta data set ready interrupt */ -//#define SNS_DELCLR 0x00000100 /* B Delta data set CTS failure interrupt */ - com_lstat[unit][0] |= (SNS_CTSS|SNS_DSRS); /* set CTS & DSR status */ + + com_lstat[unit][0] |= (SNS_CTSS|SNS_DSRS); /* set CTS & DSR status */ com_lstat[unit][0] |= (SNS_MRING); /* set char detect status */ ch = (com_lstat[unit][0] >> 8) & 0xff; chan_write_byte(GET_UADDR(uptr->u3), &ch); /* write status */ -/* Sense byte 3 Modem Control/Operation status */ -//#define SNS_HALFD 0x00000080 /* Half-duplix operation set */ -//#define SNS_MRINGE 0x00000040 /* Modem ring enabled (1) */ -//#define SNS_ACEDEF 0x00000020 /* ACE parameters defined */ -//#define SNS_DIAGM 0x00000010 /* Diagnostic mode set */ -//#define SNS_AUXOL2 0x00000008 /* Auxiliary output level 2 */ -//#define SNS_AUXOL1 0x00000004 /* Auxiliary output level 1 */ -//#define SNS_RTS 0x00000002 /* RTS Request to send set */ -//#define SNS_DTR 0x00000001 /* DTR Data terminal ready set */ -// com_lstat[unit][0] |= (SNS_RTS|SNS_DTR); /* set RTS & DTR status */ - com_lstat[unit][0] |= (SNS_DTR); /* set DTR status */ - ch = (com_lstat[unit][0] >> 0) & 0xff; + com_lstat[unit][0] |= (SNS_DTR); /* set DTR status */ + ch = (com_lstat[unit][0] >> 0) & 0xff; chan_write_byte(GET_UADDR(uptr->u3), &ch); /* write status */ + ch = (com_lstat[unit][1] >> 24) & 0xff; chan_write_byte(GET_UADDR(uptr->u3), &ch); /* write status */ + ch = (com_lstat[unit][1] >> 16) & 0xff; chan_write_byte(GET_UADDR(uptr->u3), &ch); /* write status */ + ch = (com_lstat[unit][1] >> 8) & 0xff; chan_write_byte(GET_UADDR(uptr->u3), &ch); /* write status */ + ch = (com_lstat[unit][1] >> 0) & 0xff; chan_write_byte(GET_UADDR(uptr->u3), &ch); /* write status */ + sim_debug(DEBUG_CMD, dptr, "com_startcmd Cmd SENSE return chan %04x u5-status %04x ls0 %08x ls1 %08x\n", chan, uptr->u5, com_lstat[unit][0], com_lstat[unit][1]); @@ -631,14 +590,7 @@ uint16 com_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) uptr->u4 |= ((uint32)ch)<<8; /* byte 2 of ACE data */ sim_debug(DEBUG_CMD, dptr, "com_startcmd %04x: Cmd %02x ACE bytes %08x\n", chan, cmd, uptr->u4); -#ifdef USE_INTERUPT - uptr->u5 = SNS_RDY|SNS_ONLN; /* status is online & ready */ - uptr->u3 &= LMASK; /* leave only chsa */ - uptr->u3 |= (cmd & COM_MSK); /* save command */ - sim_activate(uptr, 20); /* start us up */ -#else return SNS_CHNEND|SNS_DEVEND; /* good return */ -#endif break; @@ -646,8 +598,7 @@ uint16 com_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) uptr->u5 |= SNS_CMDREJ; /* command rejected */ sim_debug(DEBUG_CMD, dptr, "com_startcmd %04x: Cmd Invald %02x status %02x\n", chan, cmd, uptr->u5); -// return SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK; /* unit check */ - return SNS_CHNEND|STATUS_PCHK; + return SNS_CHNEND|STATUS_PCHK; /* program check */ break; } @@ -697,17 +648,11 @@ t_stat comi_srv(UNIT *uptr) newln = tmxr_poll_conn(&com_desc); /* look for connect */ if (newln >= 0) { /* rcv enb pending? */ uint16 chsa = GET_UADDR(coml_unit[newln].u3); /* get channel/sub-addr */ -// int chan = ((chsa >> 8) & 0x7f); /* get the channel number */ -// UNIT *comlp = coml_unit+ln; /* get uptr for coml line */ -// int cmd = comlp->u3 & 0xff; /* get the active cmd */ -//fprintf(stderr, "comi_srv poll chsa %04x new line %04x\r\n", chsa, newln); com_ldsc[newln].rcve = 1; /* enable rcv */ -//BAD com_ldsc[newln+8].xmte = 1; /* enable xmt for output line */ com_ldsc[newln].xmte = 1; /* enable xmt for output line */ com_sta[newln] &= ~COML_REP; /* clr pending */ /* send attention to OS here for this channel */ /* need to get chsa here for the channel */ -//fprintf(stderr, "comi_srv chsa %04x chan %04x\r\n", chsa, chan); set_devwake(chsa, SNS_ATTN|SNS_DEVEND|SNS_CHNEND); /* tell user */ } /* poll all devices for input */ @@ -718,7 +663,6 @@ t_stat comi_srv(UNIT *uptr) uint16 chsa = GET_UADDR(comlp->u3); /* get channel/sub-addr */ if (com_ldsc[ln].conn) { /* connected? */ if ((c = tmxr_getc_ln(&com_ldsc[ln]))) { /* get char */ -//fprintf(stderr, "comi_srv chsa %04x input %02x cmd %02x\r\n", chsa, c, cmd); ch = c; /* just the char */ /* echo the char out */ tmxr_putc_ln(&com_ldsc[ln], ch); /* output char */ @@ -736,12 +680,10 @@ t_stat comi_srv(UNIT *uptr) /* write byte to memory */ if (chan_write_byte(chsa, &ch)) { /* done, reading chars */ -//fprintf(stderr, "comi_srv chsa %04x input %02x complete cmd %02x\r\n", chsa, c, cmd); comlp->u3 &= LMASK; /* nothing left, clear cmd */ chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* we done */ } else { /* more to go, continue */ -//fprintf(stderr, "comi_srv chsa %04x input %02x cmd %02x\r\n", chsa, c, cmd); if (ch == '\r') { /* see if done */ comlp->u3 &= LMASK; /* nothing left, clear cmd */ chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* we done */ @@ -753,8 +695,6 @@ t_stat comi_srv(UNIT *uptr) if (((comlp->u4 & ACE_WAKE) >> 8) == ch) { /* send attention to OS here for this channel */ /* need to get chsa here for the channel */ -// fprintf(stderr, "comi_srv WAKEUP chsa %04x ch %02x wake %04x\r\n", -// chsa, ch, (comlp->u4 & ACE_WAKE)>>8); set_devwake(chsa, SNS_ATTN|SNS_DEVEND|SNS_CHNEND); /* tell user */ } } @@ -836,10 +776,8 @@ endit: if (done) /* are we done writing */ goto endit; /* done */ /* just dump the char */ -// /* xmt disabled, just wait around */ sim_debug(DEBUG_CMD, dptr, "com_srvo write dumping char 0x%02x on line %04x\n", ch, ln); tmxr_poll_tx(&com_desc); /* poll xmt */ -//?? sim_activate(uptr, coml_unit[ln].wait); /* wait */ sim_activate(uptr, uptr->wait); /* wait */ return SCPE_OK; } @@ -861,12 +799,10 @@ t_stat com_reset (DEVICE *dptr) { int32 i; -#ifndef JUNK if (com_dev.flags & DEV_DIS) /* master disabled? */ com_dev.flags |= DEV_DIS; /* disable lines */ else com_dev.flags &= ~DEV_DIS; -#endif if (com_unit[COMC].flags & UNIT_ATT) /* master att? */ sim_clock_coschedule(&com_unit[0], 200); /* activate */ for (i = 0; i < COM_LINES; i++) /* reset lines */ @@ -879,11 +815,8 @@ t_stat com_reset (DEVICE *dptr) t_stat com_attach(UNIT *uptr, CONST char *cptr) { DEVICE *dptr = get_dev(uptr); -// uint16 chsa = GET_UADDR(com_unit[COMC].u3); /* get channel/subaddress */ -// uint16 chsa = GET_UADDR(uptr->u3); /* get channel/subaddress */ t_stat r; -// chsa = GET_UADDR(com_unit[COMC].u3); /* get channel/subaddress */ r = tmxr_attach(&com_desc, uptr, cptr); /* attach */ if (r != SCPE_OK) /* error? */ return r; /* return error */ diff --git a/SEL32/sel32_con.c b/SEL32/sel32_con.c index 1bd603d..63bb30f 100644 --- a/SEL32/sel32_con.c +++ b/SEL32/sel32_con.c @@ -1,7 +1,7 @@ /* sel32_con.c: SEL 32 Class F IOP processor console. Copyright (c) 2018-2020, James C. Bevier - Portions provided by Richard Cornwell and other SIMH contributers + Portions provided by Richard Cornwell, Geert Rolf and other SIMH contributers Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -27,11 +27,6 @@ ready to recieve/transmit data when they are activated since they will transfer their block during chan_cmd. All data is transmitted as ASCII characters. - - Change History: - 12/10/2018 - force input chars to upper case if lower case - 07/18/2019 - generate interrupt for INCH/NOP commands for UTX - */ #include "sel32_defs.h" @@ -39,7 +34,6 @@ #if NUM_DEVS_CON > 0 -//#define UNIT_CON UNIT_ATTABLE | UNIT_IDLE | UNIT_DISABLE #define UNIT_CON UNIT_IDLE | UNIT_DISABLE #define CMD u3 @@ -77,7 +71,6 @@ /* sense byte 3 */ #define SNS_RDY 0x80 /* device ready */ #define SNS_ONLN 0x40 /* device online */ -//#define SNS_DSR 0x04 /* data set ready */ #define SNS_DSR 0x08 /* data set ready */ #define SNS_DCD 0x04 /* data carrier detect */ @@ -98,7 +91,6 @@ 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); @@ -145,8 +137,6 @@ DEVICE con_dev = { "CON", con_unit, NULL, con_mod, NUM_UNITS_CON, 8, 15, 1, 8, 8, NULL, NULL, &con_reset, NULL, NULL, NULL, -// &con_dib, DEV_DISABLE|DEV_DEBUG, 0, dev_debug -// &con_dib, DEV_UADDR|DEV_DISABLE|DEV_DEBUG, 0, dev_debug &con_dib, DEV_DIS|DEV_DISABLE|DEV_DEBUG, 0, dev_debug }; @@ -156,7 +146,6 @@ DEVICE con_dev = { /* initialize the console chan/unit */ void con_ini(UNIT *uptr, t_bool f) { int unit = (uptr - con_unit); /* unit 0 */ -// DEVICE *dptr = get_dev(uptr); uptr->u4 = 0; /* no input count */ con_data[unit].incnt = 0; /* no input data */ @@ -166,12 +155,10 @@ void con_ini(UNIT *uptr, t_bool f) { } /* start a console operation */ -uint16 con_preio(UNIT *uptr, uint16 chan) -{ +uint16 con_preio(UNIT *uptr, uint16 chan) { DEVICE *dptr = get_dev(uptr); int unit = (uptr - dptr->units); -// if ((uptr->CMD & 0xff00) != 0) { /* just return if busy */ if ((uptr->CMD & CON_MSK) != 0) { /* just return if busy */ sim_debug(DEBUG_CMD, &con_dev, "con_preio unit=%02x BUSY\n", unit); return SNS_BSY; @@ -203,8 +190,7 @@ uint16 con_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) { uptr->CMD |= CON_INCH2; /* save INCH command as 0xf0 */ uptr->SNS = SNS_RDY|SNS_ONLN; /* status is online & ready */ if (unit == 1) -/*#*/ sim_activate(uptr, 40); /* start us off */ -//@41 sim_activate(uptr, 40); /* start us off */ + sim_activate(uptr, 40); /* start us off */ return 0; /* no status change */ break; @@ -215,15 +201,13 @@ 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, 30); /* start us off */ -//@41 sim_activate(uptr, 40); /* start us off */ + sim_activate(uptr, 30); /* start us off */ return 0; /* no status change */ break; case CON_RD: /* 0x02 */ /* Read command */ case CON_ECHO: /* 0x0a */ /* Read command w/ECHO */ /* if output requested for input device, give error */ -// uptr->CMD &= LMASK; /* leave only chsa */ uptr->CMD &= ~CON_MSK; /* remove old CMD */ uptr->CMD |= (cmd & CON_MSK); /* save command */ if (cmd == CON_ECHO) /* echo command? */ @@ -232,19 +216,16 @@ uint16 con_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) { atbuf = 0; /* reset attention buffer */ uptr->SNS = SNS_RDY|SNS_ONLN; /* status is online & ready */ if (unit == 1) -/*#*/ sim_activate(uptr, 40); /* start us off */ -//@41 sim_activate(uptr, 40); /* start us off */ + sim_activate(uptr, 40); /* start us off */ return 0; break; case CON_NOP: /* 0x03 */ /* NOP has do nothing */ uptr->SNS = SNS_RDY|SNS_ONLN; /* status is online & ready */ -// uptr->CMD &= LMASK; /* leave only chsa */ uptr->CMD &= ~CON_MSK; /* remove old CMD */ uptr->CMD |= (cmd & CON_MSK); /* save command */ if (unit == 1) -/*#*/ sim_activate(uptr, 40); /* start us off */ -//@41 sim_activate(uptr, 40); /* start us off */ + sim_activate(uptr, 40); /* start us off */ return 0; /* no status change */ break; @@ -253,8 +234,7 @@ uint16 con_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) { uptr->CMD &= LMASK; /* leave only chsa */ uptr->CMD |= (cmd & CON_MSK); /* save command */ if (unit == 1) -/*#*/ sim_activate(uptr, 40); /* start us off */ -//@41 sim_activate(uptr, 40); /* start us off */ + sim_activate(uptr, 40); /* start us off */ return 0; /* no status change */ break; @@ -288,28 +268,16 @@ uint16 con_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) { sim_debug(DEBUG_CMD, &con_dev, "con_startcmd %04x: Invalid command %02x Sense %02x\n", chan, cmd, uptr->SNS); -// return SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK; /* unit check */ return SNS_CHNEND|STATUS_PCHK; } -#ifdef DO_DYNAMIC_DEBUG -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); int unit = (uptr - con_unit); /* unit 0 is read, unit 1 is write */ int cmd = uptr->CMD & CON_MSK; CHANP *chp = find_chanp_ptr(chsa); /* find the chanp pointer */ -#ifdef DO_ALL_CHS - uint8 ch, cp; -#else uint8 ch; -#endif sim_debug(DEBUG_CMD, &con_dev, "con_srvo enter CMD %08x chsa %04x cmd = %02x\n", uptr->CMD, chsa, cmd); @@ -353,14 +321,7 @@ 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 */ @@ -368,8 +329,8 @@ t_stat con_srvo(UNIT *uptr) { "con_srvo write CMD %08x chsa %04x cmd %02x complete\n", uptr->CMD, chsa, cmd); uptr->CMD &= LMASK; /* nothing left, command complete */ +/*RTC*/ outbusy = 0; /* output done */ - outbusy = 0; /* output done */ chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* done */ return SCPE_OK; } @@ -383,57 +344,9 @@ t_stat con_srvo(UNIT *uptr) { 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 */ - sim_debug(DEBUG_CMD, &con_dev, - "con_srvo write %02x CMD %08x chsa %04x cmd %02x complete\n", - ch, uptr->CMD, chsa, cmd); - chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* done */ - } else { - /* HACK HACK HACK */ - ch &= 0x7f; /* make 7 bit w/o parity */ -#ifdef DO_ALL_CHS - /* simh stops outputting chars to debug file if it is passed a null????? */ - if (ch == 0) /* do not pass a null char */ -//WAS ch = '@'; /* stop simh abort .... */ - ch = ' '; /* stop simh abort .... */ -#ifndef ALLOW_ESC - if (((ch >= 0x20) && (ch <= 0x7e)) || (ch == '\r') || (ch == '\n')) - cp = ch; - else - cp = '^'; - sim_debug(DEBUG_CMD, &con_dev, - "con_srvo write %01x: CMD %08x putch 0x%02x %c\n", unit, uptr->CMD, ch, cp); - sim_putchar(ch); /* output next char to device */ -#ifdef DO_DYNAMIC_DEBUG -// last2 = ((last2 << 8) & 0xffff) | cp; /* get last 2 chars */ -// if (last2 == 0x503e) { /* check for DXP> */ - last2 = ((last2 << 8) & 0xffffff) | cp; /* get last 3 chars */ - if (last2 == 0x273637) { /* check for '67 */ - cpu_dev.dctrl |= (DEBUG_INST | DEBUG_CMD | DEBUG_EXP | DEBUG_IRQ | DEBUG_TRAP); -// con_dev.dctrl |= (DEBUG_CMD | DEBUG_EXP | DEBUG_DETAIL); - } -#endif -#else - sim_putchar(ch); /* output next char to device */ -#endif -#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 */ +/*RTC*/ outbusy = 1; /* tell clock output waiting */ } return SCPE_OK; } @@ -447,6 +360,9 @@ t_stat con_srvi(UNIT *uptr) { uint8 ch; t_stat r; +// sim_clock_coschedule(uptr, tmxr_poll); /* keep polling the input */ + sim_clock_coschedule(uptr, 10000); /* keep polling the input */ + sim_debug(DEBUG_CMD, &con_dev, "con_srvi enter CMD %08x chsa %04x cmd %02x incnt %02x u4 %02x\n", uptr->CMD, chsa, cmd, con_data[unit].incnt, uptr->u4); @@ -464,7 +380,6 @@ t_stat con_srvi(UNIT *uptr) { chan_end(chsa, SNS_CHNEND|SNS_UNITCHK); /* unit check */ // fall thru return SCPE_OK; } -// return sim_activate (uptr, 20); } if ((cmd == CON_NOP) || (cmd == CON_INCH2)) { /* NOP is do nothing */ @@ -476,14 +391,12 @@ t_stat con_srvi(UNIT *uptr) { int len = chp->ccw_count; /* INCH command count */ uint32 mema = chp->ccw_addr; /* get inch or buffer addr */ //FIXME add code to test return from set_inch -// int i = set_inch(uptr, mema); /* new address */ set_inch(uptr, mema); /* new address */ con_data[unit].incnt = 0; /* buffer empty */ uptr->u4 = 0; /* no I/O yet */ sim_debug(DEBUG_CMD, &con_dev, "con_srvi INCH CMD %08x chsa %04x len %02x inch %06x\n", uptr->CMD, chsa, len, mema); -//TRY228 chan_end(chsa, SNS_CHNEND); /* INCH done */ chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* done */ } else { sim_debug(DEBUG_CMD, &con_dev, @@ -491,22 +404,15 @@ t_stat con_srvi(UNIT *uptr) { chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* NOP done */ } /* drop through to poll input */ -// return sim_activate (uptr, 20); } switch (cmd) { 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, "con_srvi readbuf unit %02x: CMD %08x read %02x incnt %02x u4 %02x len %02x\n", @@ -522,7 +428,6 @@ 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; } @@ -544,7 +449,6 @@ 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; } @@ -557,7 +461,6 @@ 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; } @@ -565,18 +468,10 @@ 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 */ ch = r & 0xff; /* drop any extra bits */ -// if (ch == 0x1b) /* esc is bad */ -// goto goout; /* skip control char */ -// if ((cmd == CON_RD) || (cmd == CON_ECHO)) { /* looking for input? */ if ((uptr->CMD & CON_INPUT) == 0) { /* looking for input? */ atbuf = 0; /* reset attention buffer */ uptr->CMD &= ~CON_ATAT; /* no @@A input */ @@ -590,26 +485,22 @@ t_stat con_srvi(UNIT *uptr) { "con_srvi handle readch unit %02x: CMD %08x read %02x u4 %02x incnt %02x\n", unit, uptr->CMD, ch, uptr->u4, con_data[unit].incnt); -//MOVED /* see if count at max, if so reset to start */ -//AFTER if (con_data[unit].incnt >= sizeof(con_data[unit].ibuff)) -//incnt++ con_data[unit].incnt = 0; /* reset buffer cnt */ - if (uptr->CMD & CON_EKO) /* ECHO requested */ sim_putchar(ch); /* ECHO the char */ /* put char in buffer */ con_data[unit].ibuff[con_data[unit].incnt++] = ch; -/*GEERT*/ /* see if count at max, if so reset to start */ -/*MOVED*/ if (con_data[unit].incnt >= sizeof(con_data[unit].ibuff)) -/*HERE**/ con_data[unit].incnt = 0; /* reset buffer cnt */ + /* see if count at max, if so reset to start */ + if (con_data[unit].incnt >= sizeof(con_data[unit].ibuff)) + con_data[unit].incnt = 0; /* reset buffer cnt */ uptr->CMD |= CON_INPUT; /* we have a char available */ sim_debug(DEBUG_CMD, &con_dev, "con_srvi readch unit %02x: CMD %08x read %02x u4 %02x incnt %02x\n", unit, uptr->CMD, ch, uptr->u4, con_data[unit].incnt); - return sim_activate (uptr, 30); /* come back real soon */ -// return sim_activate (uptr, 300); /* come back real soon */ +// return sim_activate (uptr, 30); /* come back real soon */ + return SCPE_OK; } /* not looking for input, look for attn or wakeup */ if (ch == '?') { @@ -636,7 +527,7 @@ t_stat con_srvi(UNIT *uptr) { uptr->u4 = 0; /* no input count */ con_data[unit].incnt = 0; /* no input data */ } - goto goout; + return SCPE_OK; } /* char not for us, so keep looking */ atbuf = 0; /* reset attention buffer */ @@ -664,9 +555,6 @@ t_stat con_srvi(UNIT *uptr) { "con_srvi readch2 unit %02x: CMD %08x read %02x u4 %02x incnt %02x\n", unit, uptr->CMD, ch, uptr->u4, con_data[unit].incnt); } -goout: -// return sim_activate (uptr, 5000); - tmxr_clock_coschedule_tmr(uptr, TMR_RTC, 1); /* come back soon */ return SCPE_OK; } diff --git a/SEL32/sel32_cpu.c b/SEL32/sel32_cpu.c index 4241369..4e6c4f1 100644 --- a/SEL32/sel32_cpu.c +++ b/SEL32/sel32_cpu.c @@ -1,7 +1,7 @@ /* sel32_cpu.c: Sel 32 CPU simulator Copyright (c) 2018-2020, James C. Bevier - Portions provided by Richard Cornwell and other SIMH contributers + Portions provided by Richard Cornwell, Geert Rolf and other SIMH contributers Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -271,26 +271,26 @@ 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); -extern uint32 s_fltw(uint32 val, uint32 *cc); +extern uint32 s_fixw(uint32 val, uint32 *cc); +extern uint32 s_fltw(uint32 val, uint32 *cc); extern t_uint64 s_fixd(t_uint64 val, uint32 *cc); extern t_uint64 s_fltd(t_uint64 val, uint32 *cc); -extern uint32 s_nor(uint32 reg, uint32 *exp); +extern uint32 s_nor(uint32 reg, uint32 *exp); extern t_uint64 s_nord(t_uint64 reg, uint32 *exp); -extern uint32 s_adfw(uint32 reg, uint32 mem, uint32 *cc); -extern uint32 s_sufw(uint32 reg, uint32 mem, uint32 *cc); +extern uint32 s_adfw(uint32 reg, uint32 mem, uint32 *cc); +extern uint32 s_sufw(uint32 reg, uint32 mem, uint32 *cc); extern t_uint64 s_adfd(t_uint64 reg, t_uint64 mem, uint32 *cc); extern t_uint64 s_sufd(t_uint64 reg, t_uint64 mem, uint32 *cc); -extern uint32 s_mpfw(uint32 reg, uint32 mem, uint32 *cc); -extern t_uint64 s_dvfw(uint32 reg, uint32 mem, uint32 *cc); -extern uint32 s_mpfd(t_uint64 reg, t_uint64 mem, uint32 *cc); +extern uint32 s_mpfw(uint32 reg, uint32 mem, uint32 *cc); +extern uint32 s_dvfw(uint32 reg, uint32 mem, uint32 *cc); +extern t_uint64 s_mpfd(t_uint64 reg, t_uint64 mem, uint32 *cc); extern t_uint64 s_dvfd(t_uint64 reg, t_uint64 mem, uint32 *cc); extern uint32 s_normfw(uint32 mem, uint32 *cc); extern t_uint64 s_normfd(t_uint64 mem, uint32 *cc); /* History information */ -int32 hst_p = 0; /* History pointer */ -int32 hst_lnt = 0; /* History length */ +int32 hst_p = 0; /* History pointer */ +int32 hst_lnt = 0; /* History length */ struct InstHistory *hst = NULL; /* History stack */ /* CPU data structures @@ -303,29 +303,29 @@ struct InstHistory *hst = NULL; /* History stack */ UNIT cpu_unit = /* Unit data layout for CPU */ -/* { UDATA(rtc_srv, UNIT_BINK | MODEL(MODEL_27) | MEMAMOUNT(0), MAXMEMSIZE ), 120 }; */ +/* { UDATA(rtc_srv, UNIT_BINK | MODEL(MODEL_27) | MEMAMOUNT(0), + * MAXMEMSIZE ), 120 }; */ { - NULL, /* UNIT *next */ /* next active */ - NULL, /* t_stat (*action) */ /* action routine */ - NULL, /* char *filename */ /* open file name */ - NULL, /* FILE *fileref */ /* file reference */ - NULL, /* void *filebuf */ /* memory buffer */ - 0, /* uint32 hwmark */ /* high water mark */ - 0, /* int32 time */ /* time out */ -//was UNIT_BINK|MODEL(MODEL_27)|MEMAMOUNT(1), /* uint32 flags */ /* flags */ + NULL, /* UNIT *next */ /* next active */ + NULL, /* t_stat (*action) */ /* action routine */ + NULL, /* char *filename */ /* open file name */ + NULL, /* FILE *fileref */ /* file reference */ + NULL, /* void *filebuf */ /* memory buffer */ + 0, /* uint32 hwmark */ /* high water mark */ + 0, /* int32 time */ /* time out */ UNIT_IDLE|UNIT_FIX|UNIT_BINK|MODEL(MODEL_27)|MEMAMOUNT(4), /* flags */ - 0, /* uint32 dynflags */ /* dynamic flags */ - 0x800000, /* t_addr capac */ /* capacity */ - 0, /* t_addr pos */ /* file position */ - NULL, /* void (*io_flush) */ /* io flush routine */ - 0, /* uint32 iostarttime */ /* I/O start time */ - 0, /* int32 buf */ /* buffer */ - 80, /* int32 wait */ /* wait */ + 0, /* uint32 dynflags */ /* dynamic flags */ + 0x800000, /* t_addr capac */ /* capacity */ + 0, /* t_addr pos */ /* file position */ + NULL, /* void (*io_flush) */ /* io flush routine */ + 0, /* uint32 iostarttime */ /* I/O start time */ + 0, /* int32 buf */ /* buffer */ + 80, /* int32 wait */ /* wait */ }; //UNIT cpu_unit = { UDATA (&rtc_srv, UNIT_BINK, MAXMEMSIZE) }; -REG cpu_reg[] = { +REG cpu_reg[] = { {HRDATAD(PC, PC, 24, "Program Counter"), REG_FIT}, {BRDATAD(PSD, PSD, 16, 32, 2, "Program Status Doubleword"), REG_FIT}, {BRDATAD(GPR, GPR, 16, 32, 8, "Index registers"), REG_FIT}, @@ -442,23 +442,23 @@ DEVICE cpu_dev = { }; /* CPU Instruction decode flags */ -#define INV 0x0000 /* Instruction is invalid */ -#define HLF 0x0001 /* Half word instruction */ -#define ADR 0x0002 /* Normal addressing mode */ -#define IMM 0x0004 /* Immediate mode */ -#define WRD 0x0008 /* Word addressing, no index */ -#define SCC 0x0010 /* Sets CC */ -#define RR 0x0020 /* Read source register */ -#define R1 0x0040 /* Read destination register */ -#define RB 0x0080 /* Read base register into dest */ -#define SD 0x0100 /* Stores into destination register */ -#define RNX 0x0200 /* Reads memory without sign extend */ -#define RM 0x0400 /* Reads memory */ -#define SM 0x0800 /* Stores memory */ -#define DBL 0x1000 /* Double word operation */ -#define SB 0x2000 /* Store Base register */ -#define BT 0x4000 /* Branch taken, no PC incr */ -#define SF 0x8000 /* Special flag */ +#define INV 0x0000 /* Instruction is invalid */ +#define HLF 0x0001 /* Half word instruction */ +#define ADR 0x0002 /* Normal addressing mode */ +#define IMM 0x0004 /* Immediate mode */ +#define WRD 0x0008 /* Word addressing, no index */ +#define SCC 0x0010 /* Sets CC */ +#define RR 0x0020 /* Read source register */ +#define R1 0x0040 /* Read destination register */ +#define RB 0x0080 /* Read base register into dest */ +#define SD 0x0100 /* Stores into destination register */ +#define RNX 0x0200 /* Reads memory without sign extend */ +#define RM 0x0400 /* Reads memory */ +#define SM 0x0800 /* Stores memory */ +#define DBL 0x1000 /* Double word operation */ +#define SB 0x2000 /* Store Base register */ +#define BT 0x4000 /* Branch taken, no PC incr */ +#define SF 0x8000 /* Special flag */ int nobase_mode[] = { /* 00 04 08 0C */ @@ -507,7 +507,6 @@ int nobase_mode[] = { /* B0 B4 B8 BC */ /* LM LN ADM SUM */ -// SCC|SD|RM|ADR, SCC|SD|RM|ADR, SCC|SD|RR|RM|ADR, SCC|SD|RR|RM|ADR, SCC|SD|RM|ADR, SCC|SD|RM|ADR, SD|RR|RM|ADR, SD|RR|RM|ADR, /* C0 C4 C8 CC */ @@ -574,7 +573,6 @@ int base_mode[] = { /* B0 B4 B8 BC */ /* LM LN ADM SUM */ -// SCC|SD|RM|ADR, SCC|SD|RM|ADR, SCC|SD|RR|RM|ADR, SCC|SD|RR|RM|ADR, SCC|SD|RM|ADR, SCC|SD|RM|ADR, SD|RR|RM|ADR, SD|RR|RM|ADR, /* C0 C4 C8 CC */ @@ -670,6 +668,7 @@ int base_mode[] = { /* BIT 4 = 0 (MA) A first read or write (access) to the map block (page) has not occurred */ /* = 1 (MA) A first read or write (access) to the map block (page) has occurred */ /* 5-15 = 11 most significant bits of the 24 bit real address for page */ + /* Note */ /* If a map is valid, a MAP (page) hit occurs and logical to physical translation occures */ /* If the map is not valid, a demand MAP (page) fault occures and the faulting page is provided */ @@ -736,7 +735,6 @@ t_stat load_maps(uint32 thepsd[2], uint32 lmap) MEMSIZE, mpl); TRAPSTATUS |= BIT18; /* set bit 18 of trap status */ return MAPFLT; /* no, map fault error */ -// return NPMEM; /* no, none present memory error */ } /* mpl is ok, get the msdl for given cpix */ @@ -822,8 +820,7 @@ t_stat load_maps(uint32 thepsd[2], uint32 lmap) for (j = 0; j < spc; j++, num++) { /* loop through the midl's */ uint32 pad = RMW(midl+(j<<1)); /* get page descriptor address */ if (num >= MAXMAP) { -// TRAPSTATUS |= BIT16; /* set bit 16 of trap status */ -/*96V9*/ TRAPSTATUS |= (BIT16|BIT9); /* set bit 5 of trap status */ +/*97V9*/ TRAPSTATUS |= (BIT16|BIT9); /* set bit 5 of trap status */ return MAPFLT; /* map loading overflow, map fault error */ } /* load 16 bit map descriptors */ @@ -833,8 +830,7 @@ t_stat load_maps(uint32 thepsd[2], uint32 lmap) } /* if none loaded, map fault */ if (num == 0) { -// TRAPSTATUS |= BIT16; /* set bit 16 of trap status */ -/*96V9*/ TRAPSTATUS |= (BIT16|BIT9); /* set bit 5 of trap status */ +/*97V9*/ TRAPSTATUS |= (BIT16|BIT9); /* set bit 5 of trap status */ return MAPFLT; /* attempt to load 0 maps, map fault error */ } /* clear the rest of the previously used maps */ @@ -877,11 +873,6 @@ t_stat load_maps(uint32 thepsd[2], uint32 lmap) return MAPFLT; /* no, map fault error */ } -#ifdef DO_DYNAMIC_DEBUG - /* start debugging at test 46 of cn.mmm diag */ - cpu_dev.dctrl |= (DEBUG_INST | DEBUG_CMD | DEBUG_EXP | DEBUG_IRQ); -#endif - /* check if valid real address */ mpl &= MASK24; /* clean mpl address */ if (!MEM_ADDR_OK(mpl)) { /* see if in our real memory */ @@ -899,12 +890,10 @@ npmem: } /* output O/S and User MPX entries */ -// sim_debug(DEBUG_EXP, &cpu_dev, sim_debug(DEBUG_DETAIL, &cpu_dev, "#MEMORY %06x MPL %06x MPL[0] %08x %06x MPL[%04x] %08x %06x\n", MEMSIZE, mpl, RMW(mpl), RMW(mpl+4), cpix, RMW(cpix+mpl), RMW(cpix+mpl+4)); -// sim_debug(DEBUG_EXP, &cpu_dev, sim_debug(DEBUG_DETAIL, &cpu_dev, "MEMORY2 %06x BPIX %04x cpix %04x CPIX %04x CPIXPL %04x HIWM %04x\n", MEMSIZE, BPIX, cpix, CPIX, CPIXPL, HIWM); @@ -946,8 +935,7 @@ nomaps: CPIX = cpix; /* save CPIX */ HIWM = 0; /* reset high water mark */ if ((CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9)) -// TRAPSTATUS |= BIT5; /* set bit 5 of trap status */ - TRAPSTATUS |= (BIT5|BIT9); /* set bit 5 of trap status */ + TRAPSTATUS |= (BIT5|BIT9); /* set bit 5/9 of trap status */ else TRAPSTATUS |= BIT16; /* set bit 16 of trap status */ return MAPFLT; /* map loading overflow, map fault error */ @@ -991,7 +979,7 @@ nomaps: } else { TLB[num] = 0; /* clear the TLB for non valid maps */ } -#ifndef FOR_DEBUG +#ifdef FOR_DEBUG if ((num < 0x20) || (num > (spc - 0x10))) sim_debug(DEBUG_DETAIL, &cpu_dev, "OS pad %06x=%04x map #%4x, %04x, map2 %08x, TLB %08x MAPC %08x\n", @@ -1097,12 +1085,10 @@ loaduser: CPIX = cpix; /* save CPIX */ HIWM = 0; /* reset high water mark */ if ((CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9)) -// TRAPSTATUS |= BIT5; /* set bit 5 of trap status */ - TRAPSTATUS |= (BIT5|BIT9); /* set bit 5 of trap status */ + TRAPSTATUS |= (BIT5|BIT9); /* set bit 5/9 of trap status */ else TRAPSTATUS |= BIT16; /* set bit 16 of trap status */ return MAPFLT; /* map overflow fault error */ -// goto nomaps; /* non presemt memory */ } CPIX = cpix; /* save user MPL offset (cpix) */ CPIXPL = spc; /* save user map load count */ @@ -1147,7 +1133,7 @@ loaduser: TLB[num] = 0; /* clear the TLB for non valid maps */ WMR((num<<1), map); /* store map unmodified into cache */ -#ifndef FOR_DEBUG +#ifdef FOR_DEBUG /* do partial map dump */ if ((num < 0x20) || (num > (spc+BPIX) - 0x10)) sim_debug(DEBUG_DETAIL, &cpu_dev, @@ -1195,8 +1181,7 @@ loaduser: sim_debug(DEBUG_TRAP, &cpu_dev, "load_maps User page count overflow %04x, map fault\n", num); if ((CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9)) -// TRAPSTATUS |= BIT5; /* set bit 5 of trap status */ - TRAPSTATUS |= (BIT5|BIT9); /* set bit 5 of trap status */ + TRAPSTATUS |= (BIT5|BIT9); /* set bit 5/9 of trap status */ else TRAPSTATUS |= BIT16; /* set bit 16 of trap status */ goto nomaps; /* map overflow, map fault trap */ @@ -1346,7 +1331,6 @@ t_stat RealAddr(uint32 addr, uint32 *realaddr, uint32 *prot, uint32 access) else if ((CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9)) { // V9 & 32/97 wants MACHINECHK for test 37/1 in CN.MMM & VM.MMM */ -// TRAPSTATUS |= BIT7; /* set bit 7 of trap status */ /*97&V6*/ TRAPSTATUS |= (BIT7|BIT9); /* set bit 7 of trap status */ TRAPSTATUS |= BIT28; /* set bit 28 of trap status */ return MACHINECHK_TRAP; /* diags want machine check error */ @@ -1359,18 +1343,12 @@ t_stat RealAddr(uint32 addr, uint32 *realaddr, uint32 *prot, uint32 access) offset = word & 0x1fff; /* get 13 bit page offset */ /* make sure map index is valid */ - // This change will allow MPX3x to run, but fails diags - // TRY 041420 -// WAS if (index >= (BPIX + CPIXPL)) { -// MPX3x like this: if (index > (BPIX + CPIXPL)) { -//DIAG if (index >= (BPIX + CPIXPL)) { if (index >= (BPIX + CPIXPL)) { sim_debug(DEBUG_TRAP, &cpu_dev, "RealAddr %06x word %06x loadmap gets mapfault index %04x B(%x)+C(%x) %04x\n", word, addr, index, BPIX, CPIXPL, BPIX+CPIXPL); if ((CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9)) -// TRAPSTATUS |= BIT5; /* set bit 5 of trap status */ - TRAPSTATUS |= (BIT5|BIT9); /* set bit 5 of trap status */ + TRAPSTATUS |= (BIT5|BIT9); /* set bit 5/9 of trap status */ else TRAPSTATUS |= BIT16; /* set bit 16 of trap status */ return MAPFLT; /* map fault error */ @@ -1382,7 +1360,7 @@ t_stat RealAddr(uint32 addr, uint32 *realaddr, uint32 *prot, uint32 access) if ((CPU_MODEL == MODEL_27) || (CPU_MODEL == MODEL_87)) { map = RMR((index<<1)); /* read the map reg cache contents */ raddr = TLB[index]; /* get the base address & bits */ -#ifndef MAYBE_NOT_NEEDED + if (!MEM_ADDR_OK(RMW(mpl+CPIX+4) & MASK24)) { /* check user midl */ sim_debug(DEBUG_TRAP, &cpu_dev, "RealAddr 27 & 87 map fault index %04x B+C %04x map %04x TLB %08x\n", @@ -1391,7 +1369,7 @@ t_stat RealAddr(uint32 addr, uint32 *realaddr, uint32 *prot, uint32 access) TRAPSTATUS |= BIT10; /* set bit 10 of trap status */ return MACHINECHK_TRAP; /* diags want machine check error */ } -#endif + if (((map & 0x8000) == 0) || ((raddr & BIT0) == 0)) { /* see if valid map */ sim_debug(DEBUG_TRAP, &cpu_dev, "RealAddr loadmap 0a map fault index %04x B+C %04x map %04x TLB %08x\n", @@ -1400,7 +1378,6 @@ t_stat RealAddr(uint32 addr, uint32 *realaddr, uint32 *prot, uint32 access) return MAPFLT; /* no, map fault error */ } - // diag test 34/1 fails in cn.mmm // needed for 32/27 & 32/87 /* check if valid real address */ if (!MEM_ADDR_OK(raddr & MASK24)) { /* see if address is within our memory */ @@ -1441,24 +1418,11 @@ t_stat RealAddr(uint32 addr, uint32 *realaddr, uint32 *prot, uint32 access) "RealAddr loadmap 2a non present memory fault addr %08x raddr %08x index %04x\n", addr, raddr, index); if ((CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9)) { -#ifndef TRY_AGAIN_97V6 if (access == MEM_RD) TRAPSTATUS |= BIT1; /* set bit 1 of trap status */ else if (access == MEM_WR) TRAPSTATUS |= BIT2; /* set bit 2 of trap status */ - /* returning this error fixes 34/2, but still fails 46/2 */ - return NPMEM; /* none present memory error */ -#else -// TRAPSTATUS |= BIT7; /* set bit 7 of trap status */ -/*97&V6*/ TRAPSTATUS |= (BIT7|BIT9); /* set bit 7 of trap status */ - TRAPSTATUS |= BIT12; /* set bit 12 of trap status */ - /* returning this error fails test 34/2 of mmm diag */ - return MAPFLT; /* map fault error on memory access */ -#endif -/*NEW*/// return MAPFLT; /* map fault error on memory access */ - /* returning this error fails test 34/2 of mmm diag */ -/*NEW*/// return MACHINECHK_TRAP; /* diags want machine check error */ } else TRAPSTATUS |= BIT28; /* set bit 28 of trap status */ return NPMEM; /* none present memory error */ @@ -1519,8 +1483,8 @@ t_stat RealAddr(uint32 addr, uint32 *realaddr, uint32 *prot, uint32 access) if (CPU_MODEL == MODEL_97) { // 32/97 wants MAPFLT for test 37/1 in CN.MMM TRAPSTATUS |= BIT12; /* set bit 12 of trap status */ -/*97&V6*/ TRAPSTATUS |= (BIT7|BIT9); /* set bit 7 of trap status */ -/* 97V9*/ TRAPSTATUS |= BIT10; /* set bit 10 of trap status */ +/*97&V6*/ TRAPSTATUS |= (BIT7|BIT9); /* set bit 7/9 of trap status */ +/*97&V9*/ TRAPSTATUS |= BIT10; /* set bit 10 of trap status */ return MAPFLT; /* no, map fault error */ } else if (CPU_MODEL == MODEL_V6) { @@ -1719,7 +1683,6 @@ t_stat Mem_read(uint32 addr, uint32 *data) status = RealAddr(addr, &realaddr, &prot, MEM_RD); /* convert address to real physical address */ if (status == ALLOK) { -// *data = M[realaddr >> 2]; /* valid address, get physical address contents */ *data = RMW(realaddr); /* valid address, get physical address contents */ if (((CPU_MODEL >= MODEL_V6) || (CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_67)) && (modes & MAPMODE)) { @@ -1782,7 +1745,6 @@ t_stat Mem_read(uint32 addr, uint32 *data) } if (status == MAPFLT) { if ((CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9)) -// TRAPSTATUS |= BIT12; /* set bit 12 of trap status */ /*97V9*/ TRAPSTATUS |= (BIT12|BIT16); /* set bit 12 of trap status */ else TRAPSTATUS |= BIT10; /* set bit 10 of trap status */ @@ -1842,12 +1804,11 @@ t_stat Mem_write(uint32 addr, uint32 *data) msdl = RMW(mpl+CPIX+4); /* get mpl entry for given cpix */ } nmap = RMH(msdl+(mix<<1)); /* map content from memory */ -// if ((nmap & 0x1800) == 0) { if ((nmap & 0x1000) == 0) { - nmap |= 0x1800; /* set the modify/accessed bit in the map cache entry */ - WMR((page<<1), nmap); /* store the map reg contents into cache */ - TLB[page] |= 0x18000000; /* set the modify/accessed bits in TLB too */ - WMH((msdl+(mix << 1)), nmap); /* save modified map with access bit set */ + nmap |= 0x1800; /* set the modify/accessed bit in the map cache entry */ + WMR((page<<1), nmap); /* store the map reg contents into cache */ + TLB[page] |= 0x18000000; /* set the modify/accessed bits in TLB too */ + WMH((msdl+(mix << 1)), nmap); /* save modified map with access bit set */ sim_debug(DEBUG_DETAIL, &cpu_dev, "Mem_write Waddr %06x page %04x set access bit TLB %08x map %04x nmap %04x raddr %08x\n", addr, page, TLB[page], map, nmap, raddr); @@ -1876,7 +1837,6 @@ t_stat Mem_write(uint32 addr, uint32 *data) return MPVIOL; /* return memory protection violation */ } } -// M[realaddr >> 2] = *data; /* valid address, put physical address contents */ WMW(realaddr, *data); /* valid address, put physical address contents */ } else { /* RealAddr returned an error */ @@ -1891,7 +1851,6 @@ t_stat Mem_write(uint32 addr, uint32 *data) } if (status == MAPFLT) { if ((CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9)) -// TRAPSTATUS |= BIT12; /* set bit 12 of trap status */ /*97V9*/ TRAPSTATUS |= (BIT12|BIT16); /* set bit 12 of trap status */ else TRAPSTATUS |= BIT10; /* set bit 10 of trap status */ @@ -1922,12 +1881,12 @@ void set_CCs(uint32 value, int ovr) } /* retain these values across calls to sim_instr */ -uint32 skipinstr = 0; /* Skip test for interrupt on this instruction */ -uint32 drop_nop = 0; /* Set if right hw instruction is a nop */ -uint32 OIR=0; /* Original Instruction register */ -uint32 OPSD1=0; /* Original PSD1 */ -uint32 OPSD2=0; /* Original PSD2 */ -uint32 TPSD[2]; /* Temp PSD */ +uint32 skipinstr = 0; /* Skip test for interrupt on this instruction */ +uint32 drop_nop = 0; /* Set if right hw instruction is a nop */ +uint32 OIR=0; /* Original Instruction register */ +uint32 OPSD1=0; /* Original PSD1 */ +uint32 OPSD2=0; /* Original PSD2 */ +uint32 TPSD[2]; /* Temp PSD */ /* Opcode definitions */ /* called from simulator */ @@ -1999,7 +1958,7 @@ wait_loop: } if (skipinstr) { /* need to skip interrupt test? */ -#ifndef NOTNOW +#ifdef NOTNOW sim_debug(DEBUG_IRQ, &cpu_dev, "Skipinstr %1x zeroed after skip PSD1 %08x PSD2 %08x CPUSTATUS %08x\n", skipinstr, PSD1, PSD2, CPUSTATUS); @@ -2009,39 +1968,31 @@ wait_loop: } /* process any channel programs */ -//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_XIO, &cpu_dev, - "CPU RDYQ entry for chsa %04x starting\n", chsa); - stat = cont_chan(chsa); /* resume the channel program */ - if (stat) + /* we have entries, continue channel program */ + if (RDYQ_Get(&chsa) == SCPE_OK) { /* get chsa for program */ sim_debug(DEBUG_XIO, &cpu_dev, - "CPU RDYQ entry for chsa %04x processed\n", chsa); - } - /* 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 + "CPU RDYQ entry for chsa %04x starting\n", chsa); + stat = cont_chan(chsa); /* resume the channel program */ + if (stat) + sim_debug(DEBUG_XIO, &cpu_dev, + "CPU RDYQ entry for chsa %04x processed\n", chsa); + } + /* 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 = 10; /* wait 10 instructions */ + waitqcnt = 20; /* wait 10 instructions */ + } else waitqcnt -= 1; /* wait another instruction */ } else - 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 */ +// waitqcnt = 35; /* wait 10 instructions */ + waitqcnt = 20; /* wait 10 instructions */ //040120 waitqcnt = 10; /* wait 10 instructions */ @@ -2086,22 +2037,19 @@ wait_loop: /* Class F I/O spec says to reset active interrupt if user's */ /* interrupt service routine runs with interrupts blocked */ if (((t & 0x0f800000) == 0x0f000000) || /* if class F clear interrupt */ -//HANGS DEXP if (((t & 0x0f000000) == 0x0f000000) || /* if class F clear interrupt */ -//DIAGS ((t & 0x0f807fff) == 0x00807f06) || /* RT Clock */ /*NEW*/ ((t & 0x0000ffff) == 0x00007f06) || /* RT Clock */ -//DIAGS ((t & 0x0f807fff) == 0x03007f04)) { /* Interval timer */ /*NEW*/ ((t & 0x0f00ffff) == 0x03007f04)) { /* Interval timer */ /* 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 +#ifdef LEAVE_AUTO_INT_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 simi %02x\n", il, INTS[il], il+0x80, SPAD[il+0x80], sim_interval); -/*TRY*/ } + } } else { sim_debug(DEBUG_IRQ, &cpu_dev, "<|>RUN ACTIVE interrupt INTS[%02x] %08x SPAD[%02x] %08x\n", @@ -2159,10 +2107,10 @@ wait_loop: SPAD[0xf5] = PSD2; /* save the current PSD2 */ SPAD[0xf9] = CPUSTATUS; /* save the cpu status in SPAD */ loading = 0; /* we are done loading */ -#ifndef NOTNOW - sim_debug(DEBUG_IRQ, &cpu_dev, - "Load Skipinstr %1x set loading PSD1 %08x PSD2 %08x CPUSTATUS %08x\n", - skipinstr, PSD1, PSD2, CPUSTATUS); +#ifdef NOTNOW + sim_debug(DEBUG_IRQ, &cpu_dev, + "Load Skipinstr %1x set loading PSD1 %08x PSD2 %08x CPUSTATUS %08x\n", + skipinstr, PSD1, PSD2, CPUSTATUS); #endif skipinstr = 1; /* skip next interrupt test only once */ } @@ -2182,7 +2130,7 @@ wait_loop: TRAPME = attention_trap; /* get trap number */ attention_trap = 0; /* clear flag */ sim_debug(DEBUG_XIO, &cpu_dev, "Attention TRAP %04x\n", TRAPME); -#ifndef NOTNOW +#ifdef NOTNOW sim_debug(DEBUG_IRQ, &cpu_dev, "Skipinstr %1x set @ attn int PSD1 %08x PSD2 %08x CPUSTATUS %08x\n", skipinstr, PSD1, PSD2, CPUSTATUS); @@ -2230,11 +2178,11 @@ 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)) { -#ifndef NOTNOW +#ifdef NOTNOW if (skipinstr) - sim_debug(DEBUG_IRQ, &cpu_dev, - "1Rt HW instruction skipinstr %1x is set PSD1 %08x PSD2 %08x CPUSTATUS %08x\n", - skipinstr, PSD1, PSD2, CPUSTATUS); + sim_debug(DEBUG_IRQ, &cpu_dev, + "1Rt HW instruction skipinstr %1x is set PSD1 %08x PSD2 %08x CPUSTATUS %08x\n", + skipinstr, PSD1, PSD2, CPUSTATUS); #endif drop_nop = 0; /* not dropping nop for these machines */ goto exec; /* machine does not drop nop instructions */ @@ -2242,15 +2190,15 @@ skipi: /* We have 67 or V6 and have a rt hw instruction */ 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); +// fprintf(stderr, "RIGHT HW skip NOP instr %x skip nop at %x\n", IR, PSD1); 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); + 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 */ } - if (skipinstr) - sim_debug(DEBUG_IRQ, &cpu_dev, + if (skipinstr) + sim_debug(DEBUG_IRQ, &cpu_dev, "3Rt HW instruction skipinstr %1x is set PSD1 %08x PSD2 %08x CPUSTATUS %08x\n", skipinstr, PSD1, PSD2, CPUSTATUS); } else { @@ -2350,7 +2298,7 @@ exec: addr += (BR[ix] & MASK24); /* if not zero, add to base reg contents */ FC = ((IR & F_BIT) ? 4 : 0); /* get F bit from original instruction */ FC |= addr & 3; /* set new C bits to address from orig or regs */ -/*TRY*/ addr &= MASK24; /* make pure 24 bit addr */ + addr &= MASK24; /* make pure 24 bit addr */ break; case INV: TRAPME = UNDEFINSTR_TRAP; /* Undefined Instruction Trap */ @@ -2439,7 +2387,7 @@ exec: case WRD: /* Word addressing, no index */ bc = 0xC0000000; /* set bits 0, 1 for instruction if not indirect */ t = IR; /* get current IR */ -/*TRY*/ addr &= MASK24; /* make pure 24 bit addr */ + addr &= MASK24; /* make pure 24 bit addr */ while ((t & IND) != 0) { /* process indirection */ if ((TRAPME = Mem_read(addr, &temp))) { /* get the word from memory */ sim_debug(DEBUG_TRAP, &cpu_dev, @@ -2470,13 +2418,6 @@ exec: dest = (t_uint64)addr; /* make into 64 bit variable */ break; case INV: /* Invalid instruction */ -#ifdef WHAT_IS_THIS - if ((TRAPME = Mem_read(addr, &temp))) { /* get the word from memory */ - sim_debug(DEBUG_TRAP, &cpu_dev, - "case INV Mem_read status %02x @ %08x\n", TRAPME, addr); - goto newpsd; /* memory read error or map fault */ - } -#endif TRAPME = UNDEFINSTR_TRAP; /* Undefined Instruction Trap */ if ((CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9)) TRAPSTATUS |= BIT0; /* set bit 0 of trap status */ @@ -2651,7 +2592,7 @@ exec: } sim_debug(DEBUG_EXP, &cpu_dev, "Starting HALT instruction\n"); -// if (cpu_dev.dctrl & DEBUG_EXP) { +// if (cpu_dev.dctrl & DEBUG_EXP) { sim_debug(DEBUG_EXP, &cpu_dev, "\n[][][][][][][][][][] HALT [][][][][][][][][][]\n"); sim_debug(DEBUG_EXP, &cpu_dev, "PSD1 %.8x PSD2 %.8x TRAPME %.4x CPUSTATUS %08x\n", PSD1, PSD2, TRAPME, CPUSTATUS); @@ -2659,7 +2600,7 @@ exec: sim_debug(DEBUG_EXP, &cpu_dev, "GPR[%d] %.8x GPR[%d] %.8x\n", ix, GPR[ix], ix+1, GPR[ix+1]); } sim_debug(DEBUG_EXP, &cpu_dev, "[][][][][][][][][][] HALT [][][][][][][][][][]\n"); -// } +// } fprintf(stdout, "\r\n[][][][][][][][][][] HALT [][][][][][][][][][]\r\n"); fprintf(stdout, "PSD1 %.8x PSD2 %.8x TRAPME %.4x\r\n", PSD1, PSD2, TRAPME); for (ix=0; ix<8; ix+=2) { @@ -2774,7 +2715,7 @@ exec: } if (CPUSTATUS & 0x80) { /* see if old mode is blocked */ irq_pend = 1; /* start scanning interrupts again */ - if (irq_auto ) { + if (irq_auto) { /*AIR*/ INTS[irq_auto] &= ~INTS_ACT; /* deactivate specified int level */ /*AIR*/ SPAD[irq_auto+0x80] &= ~SINT_ACT; /* deactivate in SPAD too */ sim_debug(DEBUG_IRQ, &cpu_dev, @@ -2796,8 +2737,8 @@ exec: break; case 0x9: /* RDSTS */ GPR[reg] = CPUSTATUS; /* get CPU status word */ -sim_debug(DEBUG_CMD, &cpu_dev, -"RDSTS CPUSTATUS %08x SPAD[0xf9] %08x\n", CPUSTATUS, SPAD[0xf9]); +//sim_debug(DEBUG_CMD, &cpu_dev, +//"RDSTS CPUSTATUS %08x SPAD[0xf9] %08x\n", CPUSTATUS, SPAD[0xf9]); #ifdef DO_DYNAMIC_DEBUG /* start debugging */ cpu_dev.dctrl |= (DEBUG_INST | DEBUG_TRAP | DEBUG_EXP | DEBUG_IRQ); @@ -3555,15 +3496,15 @@ tbr: /* handle basemode TBR too * i_flags |= BT; /* we changed the PC, so no PC update */ break; - case 0x1: /* INV */ - case 0x3: /* INV */ - case 0x6: /* INV */ - case 0x7: /* INV */ - case 0x9: /* INV */ - case 0xA: /* INV */ - case 0xB: /* INV */ - case 0xD: /* INV */ - case 0xF: /* INV */ + case 0x1: /* INV */ + case 0x3: /* INV */ + case 0x6: /* INV */ + case 0x7: /* INV */ + case 0x9: /* INV */ + case 0xA: /* INV */ + case 0xB: /* INV */ + case 0xD: /* INV */ + case 0xF: /* INV */ TRAPME = UNDEFINSTR_TRAP; /* Undefined Instruction Trap */ if ((CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9)) TRAPSTATUS |= BIT0; /* set bit 0 of trap status */ @@ -3844,15 +3785,8 @@ skipit: goto newpsd; /* program error */ } bc = PSD2 & 0x3ff8; /* get copy of cpix */ -#ifdef DIAG_HACK - if ((IR & 0xffff) == 2 ) /* if nop in rt hw, bump pc a word */ - PSD1 = (PSD1 + 4) | (((PSD1 & 2) >> 1) & 1); - else - PSD1 = (PSD1 + 2) | (((PSD1 & 2) >> 1) & 1); -#else /* this will skip over rt hw instruction if any */ PSD1 = (PSD1 + 4) | (((PSD1 & 2) >> 1) & 1); /* bump pc by 1 wd */ -#endif M[t>>2] = PSD1 & 0xfffffffe; /* store PSD 1 + 1HW to point to next instruction */ M[(t>>2)+1] = PSD2; /* store PSD 2 */ PSD1 = M[(t>>2)+2]; /* get new PSD 1 */ @@ -3880,7 +3814,8 @@ skipit: /*AIR*/ INTS[irq_auto] &= ~INTS_ACT; /* deactivate specified int level */ /*AIR*/ SPAD[irq_auto+0x80] &= ~SINT_ACT; /* deactivate in SPAD too */ sim_debug(DEBUG_IRQ, &cpu_dev, - "<|>IntX deactivate level %02x at CALM PSD1 %08x\n", irq_auto, PSD1); + "<|>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 */ } @@ -3896,7 +3831,7 @@ skipit: TRAPME = 0; /* not to be processed as trap */ goto newpsd; /* new psd loaded */ } else { -// fprintf(stderr, "got CALM trap\r\n"); +// fprintf(stderr, "got CALM trap\r\n"); goto inv; /* invalid instr */ } break; @@ -3905,9 +3840,9 @@ skipit: if (modes & BASEBIT) /* see if based */ goto inv; /* invalid instruction in based mode */ if (modes & EXTDBIT) { /* see if extended mode */ -/*TRY*/ dest = (t_uint64)(addr&MASK24); /* just pure 24 bit address */ + dest = (t_uint64)(addr&MASK24); /* just pure 24 bit address */ } else { /* use bits 13-31 */ -/*TRY*/ dest = (t_uint64)((addr&0x7ffff) | ((FC & 4) << 17)); /* F bit to bit 12 */ + dest = (t_uint64)((addr&0x7ffff) | ((FC & 4) << 17)); /* F bit to bit 12 */ } break; @@ -3937,38 +3872,6 @@ 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 */ -// } - /* test for zero reg value */ - if (temp == 0) { /* reg value is zero */ - temp2 = s_normfw(addr, &CC); /* normalize addr value */ - if (CC & CC1BIT) { - CC = 0; /* remove addr except */ - if (temp2 & FSIGN) - CC |= CC3BIT; /* CC3 for neg */ - else if (temp2 == 0) - CC |= CC4BIT; /* CC4 for zero */ - else - CC |= CC2BIT; /* CC2 for greater than zero */ - } - } - else - if (addr == 0) { /* mem value is zero */ - temp2 = s_normfw(temp, &CC); /* normalize addr value */ - if (CC & CC1BIT) { - CC = 0; /* remove addr except */ - if (temp2 & FSIGN) - CC |= CC3BIT; /* CC3 for neg */ - else if (temp2 == 0) - CC |= CC4BIT; /* CC4 for zero */ - else - CC |= CC2BIT; /* CC2 for greater than zero */ - } - } - 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", @@ -4121,34 +4024,6 @@ 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) { - CC = 0; /* remove addr except */ - if (dest & DMSIGN) - CC |= CC3BIT; /* CC3 for neg */ - else if (dest == 0) - CC |= CC4BIT; /* CC4 for zero */ - else - CC |= CC2BIT; /* CC2 for greater than zero */ - } - } - else - if (source == 0) { /* memory value zero? */ - dest = s_normfd(td, &CC); /* normalize reg value */ - if (CC & CC1BIT) { - CC = 0; /* remove addr except */ - if (dest & DMSIGN) - CC |= CC3BIT; /* CC3 for neg */ - else if (dest == 0) - CC |= CC4BIT; /* CC4 for zero */ - else - CC |= CC2BIT; /* CC2 for greater than zero */ - } - } - else -#endif dest = s_adfd(td, source, &CC); /* do ADFD */ sim_debug(DEBUG_EXP, &cpu_dev, @@ -4386,7 +4261,6 @@ doovr4: goto inv; /* invalid instruction in basemode */ if (reg & 1) { /* odd reg specified? */ /* Spec fault */ -#ifndef NO_HACK /* HACK HACK HACK for DIAGS */ if (CPU_MODEL <= MODEL_27) { /* DIAG error for 32/27 only */ if ((PSD1 & 2) == 0) /* if lf hw instruction */ @@ -4394,7 +4268,6 @@ doovr4: else PSD1 &= ~3; /* fake out 32/27 diag error */ } -#endif TRAPME = ADDRSPEC_TRAP; /* bad reg address, error */ goto newpsd; /* go execute the trap now */ } @@ -4418,7 +4291,6 @@ doovr4: /* sreg has Rs */ if (reg & 1) { /* Spec fault */ -#ifndef NO_HACK /* HACK HACK HACK for DIAGS */ if (CPU_MODEL <= MODEL_27) { /* DIAG error for 32/27 only */ if ((PSD1 & 2) == 0) /* if lf hw instruction */ @@ -4426,13 +4298,12 @@ doovr4: else PSD1 &= ~3; /* fake out 32/27 diag error */ } -#endif TRAPME = ADDRSPEC_TRAP; /* bad reg address, error */ goto newpsd; /* go execute the trap now */ } if (opr & 0xf) { /* any subop not zero is error */ if ((CPU_MODEL == MODEL_97) || (CPU_MODEL == MODEL_V9)) - TRAPSTATUS |= BIT0; /* set bit 0 of trap status */ + TRAPSTATUS |= BIT0; /* set bit 0 of trap status */ TRAPME = UNDEFINSTR_TRAP; /* Undefined Instruction Trap */ goto newpsd; /* handle trap */ } @@ -4493,7 +4364,7 @@ doovr3: case 0x50>>2: /* 0x50 INV - SD|ADR */ /* LA basemode LABRM */ if ((modes & BASEBIT) == 0) /* see if nonbased */ goto inv; /* invalid instruction in nonbased mode */ -/*TRY*/ dest = (t_uint64)(addr&MASK24); /* just pure 24 bit address */ + dest = (t_uint64)(addr&MASK24); /* just pure 24 bit address */ break; case 0x54>>2: /* 0x54 SM|ADR - INV */ /* (basemode STWBR) */ @@ -5034,19 +4905,19 @@ meoa: /* merge point for eor, and, or */ if (dbl) { /* we need to and both regs with R4 */ t_uint64 nm = (((t_uint64)GPR[4]) << 32) | (((t_uint64)GPR[4]) & D32RMASK); - td = dest; /* save dest */ + td = dest; /* save dest */ dest ^= source; - dest &= nm; /* mask both regs with reg 4 contents */ + dest &= nm; /* mask both regs with reg 4 contents */ } else { - td = dest; /* save dest */ - dest ^= source; /* <= 32 bits, so just do lower 32 bits */ - dest &= (((t_uint64)GPR[4]) & D32RMASK); /* mask with reg 4 contents */ + td = dest; /* save dest */ + dest ^= source; /* <= 32 bits, so just do lower 32 bits */ + dest &= (((t_uint64)GPR[4]) & D32RMASK); /* mask with reg 4 contents */ } CC = 0; if (dest == 0ll) CC |= CC4BIT; - PSD1 &= 0x87FFFFFE; /* clear the old CC's from PSD1 */ - PSD1 |= CC; /* update the CC's in the PSD */ + PSD1 &= 0x87FFFFFE; /* clear the old CC's from PSD1 */ + PSD1 |= CC; /* update the CC's in the PSD */ break; case 0x98>>2: /* 0x98 ADR - ADR */ /* SBM */ @@ -5212,11 +5083,11 @@ meoa: /* merge point for eor, and, or */ "\n\tR0=%.8x R1=%.8x R2=%.8x R3=%.8x", GPR[0], GPR[1], GPR[2], GPR[3]); sim_debug(DEBUG_INST, &cpu_dev, " R4=%.8x R5=%.8x R6=%.8x R7=%.8x\n", GPR[4], GPR[5], GPR[6], GPR[7]); -#ifndef NOTNOW - if (skipinstr) - sim_debug(DEBUG_IRQ, &cpu_dev, - "EXM skipinstr %x reset irq_pend %x PSD1 %08x PSD2 %08x CPUSTATUS %08x\n", - skipinstr, irq_pend, PSD1, PSD2, CPUSTATUS); +#ifdef NOTNOW + if (skipinstr) + sim_debug(DEBUG_IRQ, &cpu_dev, + "EXM skipinstr %x reset irq_pend %x PSD1 %08x PSD2 %08x CPUSTATUS %08x\n", + skipinstr, irq_pend, PSD1, PSD2, CPUSTATUS); #endif /*DIAG*/ skipinstr = 0; /* only test this once */ goto exec; /* go execute the instruction */ @@ -5427,17 +5298,17 @@ doovr: break; case 0x3: /* MPI */ - if (reg & 1) { /* see if odd reg specified */ - TRAPME = ADDRSPEC_TRAP; /* bad reg address, error */ - goto newpsd; /* go execute the trap now */ + if (reg & 1) { /* see if odd reg specified */ + TRAPME = ADDRSPEC_TRAP; /* bad reg address, error */ + goto newpsd; /* go execute the trap now */ } /* change immediate value into a 64 bit value */ source = ((t_uint64)(addr & FMASK)) | ((addr & FSIGN) ? D32LMASK : 0); - temp = GPR[reg+1]; /* get reg multiplier */ + temp = GPR[reg+1]; /* get reg multiplier */ dest = ((t_uint64)(temp & FMASK)) | ((temp & FSIGN) ? D32LMASK : 0); - dest = dest * source; /* do the multiply */ - i_flags |= (SD|SCC); /* save regs and set CC's */ - dbl = 1; /* double reg save */ + dest = dest * source; /* do the multiply */ + i_flags |= (SD|SCC); /* save regs and set CC's */ + dbl = 1; /* double reg save */ break; case 0x4: /* DVI */ @@ -5618,7 +5489,7 @@ doovr2: "\n\tR0=%.8x R1=%.8x R2=%.8x R3=%.8x", GPR[0], GPR[1], GPR[2], GPR[3]); sim_debug(DEBUG_INST, &cpu_dev, " R4=%.8x R5=%.8x R6=%.8x R7=%.8x\n", GPR[4], GPR[5], GPR[6], GPR[7]); -#ifndef NOTNOW +#ifdef NOTNOW if (skipinstr) sim_debug(DEBUG_IRQ, &cpu_dev, "EXR skipinstr %x reset irq_pend %x PSD1 %08x PSD2 %08x CPUSTATUS %08x\n", @@ -5767,43 +5638,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 */ - if (temp2 == 0) { /* reg value is zero */ - temp = s_normfw(addr, &CC); /* normalize addr value */ - if (CC & CC1BIT) { - CC = 0; /* remove addr except */ - if (temp & FSIGN) - CC |= CC3BIT; /* CC3 for neg */ - else if (temp == 0) - CC |= CC4BIT; /* CC4 for zero */ - else - CC |= CC2BIT; /* CC2 for greater than zero */ - } - } - else -// if ((addr == 0) && ((temp2 & 0x80000000) == 0)) { /* is reg value zero */ - if (addr == 0) { /* mem value is zero */ - temp = s_normfw(temp2, &CC); /* normalize addr value */ - if (CC & CC1BIT) { - CC = 0; /* remove addr except */ - if (temp & FSIGN) - CC |= CC3BIT; /* CC3 for neg */ - else if (temp == 0) - CC |= CC4BIT; /* CC4 for zero */ - else - CC |= CC2BIT; /* CC2 for greater than zero */ - } - } - else -#endif - temp = s_adfw(temp2, addr, &CC); /* do ADFW */ -// } else { -// /* s_sufw will negate the value before calling add */ -// temp = s_sufw(temp2, addr, &CC); /* do SUFW */ -// } + temp = s_adfw(temp2, addr, &CC); /* do ADFW */ sim_debug(DEBUG_EXP, &cpu_dev, "%s GPR[%d] %08x addr %08x result %08x CC %08x\n", (opr&8) ? "ADFW":"SUFW", reg, GPR[reg], addr, temp, CC); @@ -5831,43 +5666,9 @@ doovr2: td |= (t_uint64)GPR[reg+1]; /* insert low order reg value */ /* source has 64 bit memory data */ if ((opr & 8) == 0) { /* Was it SUFD? */ - td = NEGATE32(td); /* make negative for subtract */ + source = NEGATE32(source); /* 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 */ - dest = s_normfd(source, &CC); /* normalize addr value */ - if (CC & CC1BIT) { - CC = 0; /* remove addr except */ - if (dest & DMSIGN) - CC |= CC3BIT; /* CC3 for neg */ - else if (dest == 0) - CC |= CC4BIT; /* CC4 for zero */ - else - CC |= CC2BIT; /* CC2 for greater than zero */ - } - } - else - if (source == 0) { /* memory value zero? */ - dest = s_normfd(td, &CC); /* normalize reg value */ - if (CC & CC1BIT) { - CC = 0; /* remove addr except */ - if (dest & DMSIGN) - CC |= CC3BIT; /* CC3 for neg */ - else if (dest == 0) - CC |= CC4BIT; /* CC4 for zero */ - else - CC |= CC2BIT; /* CC2 for greater than zero */ - } - } - else -#endif - dest = s_adfd(td, source, &CC); /* do ADFD */ -// } else { -// /* s_sufd will negate the memory value before calling add */ -// dest = s_sufd(td, source, &CC); /* do SUFD */ -// } + dest = s_adfd(td, source, &CC); /* do ADFD */ sim_debug(DEBUG_EXP, &cpu_dev, "%s GPR[%d] %08x %08x src %016llx result %016llx CC %08x\n", (opr&8) ? "ADFD":"SUFD", reg, GPR[reg], GPR[reg+1], source, dest, CC); @@ -6121,8 +5922,9 @@ doovr2: if (dest != 0) { /* if reg is not 0, take the branch */ /* we are taking the branch, set CC's if indirect, else leave'm */ /* update the PSD with new address */ -#if 0 /* set to 1 to stop branch to self while tracing, for now */ -/* FIXME */ if (PC == (addr & 0xFFFFFC)) { /* BIB to current PC, bump branch addr */ + +#if 0 /* set #if to 1 to stop branch to self while tracing, for now */ + if (PC == (addr & 0xFFFFFC)) { /* BIB to current PC, bump branch addr */ addr += 4; // fprintf(stderr, "BI? stopping BIB $ addr %x PC %x\r\n", addr, PC); dest = 0; /* force reg to zero */ @@ -6267,56 +6069,15 @@ doovr2: if (PSD2 & MAPBIT) { /* set mapped mode in cpu status */ CPUSTATUS |= 0x00800000; /* set bit 8 of cpu status */ -// sim_debug(DEBUG_EXP, &cpu_dev, sim_debug(DEBUG_DETAIL, &cpu_dev, "B4 LPSDCM temp %06x TPSD %08x %08x PSD %08x %08x\n", temp, TPSD[0], TPSD[1], PSD1, PSD2); -// sim_debug(DEBUG_EXP, &cpu_dev, sim_debug(DEBUG_DETAIL, &cpu_dev, "B4 LPSDCM BPIX %04x CPIX %04x CPIXPL %04x\n", BPIX, CPIX, CPIXPL); -#ifdef FOR_DEBUG_MPX_041420 - { - int i; - uint32 mpl = SPAD[0xf3]; /* get mpl from spad address */ - uint32 osmidl = RMW(mpl); /* get O/S map count & retain flag from MPL[0] */ - uint32 osmsdl = RMW(mpl+4); /* get msdl pointer for OS from MPL[1] */ - int spc = osmidl & MASK16; /* get 16 bit O/S segment description count */ - uint32 cpix = PSD2 & 0x3ff8; /* get cpix 11 bit offset from psd wd 2 */ - uint32 midl = RMW(mpl+cpix); /* get midl entry for given user cpix */ - uint32 msdl = RMW(mpl+cpix+4); /* get mpl entry wd 1 for given cpix */ - int osc = osmidl & MASK16; /* get 16 bit O/S segment description count */ - sim_debug(DEBUG_EXP, &cpu_dev, - "B4 LPSDCM O/S cnt %04x User cnt %04x Last cnt %04x\n", - osmidl&MASK16, midl&MASK16, CPIXPL); - for (i=0; i (osc - 0x10))) - sim_debug(DEBUG_TRAP, &cpu_dev, - "OS pad %06x=%04x map #%3x, %04x, map2 %08x, TLB %08x MAPC %08x\n", - pad, map, i, map, (((map << 16) & 0xf8000000) | ((map & 0x7ff) << 13)), - TLB[i], MAPC[i/2]); - } - - spc = midl & MASK16; /* get 16 bit user segment description count */ - for (i=0; i (spc+osc) - 0x10)) - sim_debug(DEBUG_EXP, &cpu_dev, - "UserV pad %06x=%04x map #%3x, %04x, map2 %08x, TLB %08x, MAPC %08x\n", - pad, map, osc+i, map, (((map << 16) & 0xf8000000)|(map & 0x7ff)<<13)|0x04000000, - TLB[BPIX+i], MAPC[(BPIX+i)/2]); - } - } -#endif /* this mod fixes MPX 1.X 1st swapr load */ /* any O/S or user maps yet? */ - /* any user maps yet? */ if (((CPIX != 0) && (CPIXPL == 0)) && (PSD2 & RETMBIT)) { PSD2 &= ~RETMBIT; /* no, turn off retain bit in PSD2 */ sim_debug(DEBUG_EXP, &cpu_dev, "Turn off retain bit\n"); @@ -6339,19 +6100,15 @@ doovr2: if ((PSD2 & RETMBIT) == 0) { /* don't load maps if retain bit set */ /* we need to load the new maps */ TRAPME = load_maps(PSD, 0); /* load maps for new PSD */ -// sim_debug(DEBUG_EXP, &cpu_dev, sim_debug(DEBUG_DETAIL, &cpu_dev, "AF LPSDCM TPSD %08x %08x PSD %08x %08x TRAPME %02x\n", TPSD[0], TPSD[1], PSD1, PSD2, TRAPME); -// sim_debug(DEBUG_EXP, &cpu_dev, sim_debug(DEBUG_DETAIL, &cpu_dev, "AF LPSDCM BPIX %04x CPIX %04x CPIXPL %04x\n", BPIX, CPIX, CPIXPL); -// sim_debug(DEBUG_EXP, &cpu_dev, sim_debug(DEBUG_DETAIL, &cpu_dev, "AF LPSDCM OS MAPC[0-5] %08x %08x %08x %08x %08x %08x\n", MAPC[0], MAPC[1], MAPC[2], MAPC[3], MAPC[4], MAPC[5]); -// sim_debug(DEBUG_EXP, &cpu_dev, sim_debug(DEBUG_DETAIL, &cpu_dev, "AF LPSDCM US MAPC[%x-%x] %08x %08x %08x %08x %08x %08x\n", BPIX, BPIX+5, MAPC[BPIX], MAPC[BPIX+1], MAPC[BPIX+2], @@ -6365,7 +6122,6 @@ doovr2: TRAPME, PSD1, PSD2, BPIX, CPIXPL); } PSD2 &= ~RETMBIT; /* turn off retain bit in PSD2 */ -///* 041820*/ skipinstr = 1; /* skip interrupt test */ } else { /* LPSD */ /* if cpix is zero, copy cpix from PSD2 in SPAD[0xf5] */ @@ -6457,11 +6213,6 @@ doovr2: 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 */ @@ -6574,7 +6325,7 @@ doovr2: irq_pend = 1; /* start scanning interrupts again */ /* instruction following a DAI can not be interrupted */ /* skip tests for interrupts if this is the case */ -#ifndef NOTNOW +#ifdef NOTNOW sim_debug(DEBUG_IRQ, &cpu_dev, "DAI lev %02x Skipinstr %1x set PSD1 %08x PSD2 %08x CPUSTATUS %08x\n", prior, skipinstr, PSD1, PSD2, CPUSTATUS); @@ -6614,10 +6365,6 @@ doovr2: /* return status has new CC's in bits 1-4 of status word */ /* insert status CCs */ PSD1 = ((PSD1 & 0x87fffffe) | (status & 0x78000000)); -#ifdef DO_DYNAMIC_DEBUG - /* start debugging */ - cpu_dev.dctrl |= (DEBUG_INST | DEBUG_CMD | DEBUG_EXP | DEBUG_IRQ | DEBUG_TRAP); -#endif } else { /* may want to handle class E someday */ // if ((TRAPME = testEIO(device, testcode, &status))) @@ -6815,11 +6562,6 @@ mcheck: sim_debug(DEBUG_XIO, &cpu_dev, "HIO HALTXIO ret chan %04x chsa %04x status %08x\n", chan, rchsa, rstatus); -#ifndef NOTNOW - sim_debug(DEBUG_IRQ, &cpu_dev, - "HIO skipinstr %x irq_pend %x PSD1 %08x PSD2 %08x CPUSTATUS %08x\n", - skipinstr, irq_pend, PSD1, PSD2, CPUSTATUS); -#endif break; case 0x07: /* Grab controller GRIO n/u */ @@ -6920,17 +6662,18 @@ mcheck: SPAD[ix+0x80] &= ~SINT_ACT; /* deactivate in SPAD too */ irq_pend = 1; /* start scanning interrupts again */ skipinstr = 1; /* skip interrupt test */ -#ifndef NOTNOW +#ifdef NOTNOW 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 -/*XXX*/ drop_nop = 0; /* nothing to drop */ + drop_nop = 0; /* nothing to drop */ PSD1 = ((PSD1 & 0x87fffffe) | (rstatus & 0x78000000)); /* insert status */ break; } /* end of XIO switch */ break; } /* End of Instruction Switch */ + /* [*][*][*][*][*][*][*][*][*][*][*][*][*][*][*][*][*][*][*][*][*][*] */ /* any instruction with an arithmetic exception will still end up here */ @@ -7383,7 +7126,7 @@ t_stat cpu_reset(DEVICE *dptr) TRAPSTATUS = CPU_MODEL; /* clear all trap status except cpu type */ CMCR = 0; /* No Cache Enabled */ SMCR = 0; /* No Shared Memory Enabled */ -//@42 CMSMC = 0xfffffe10; /* No V9 Cache/Shadow Memory Configuration */ +//@42 CMSMC = 0xfffffe10; /* No V9 Cache/Shadow Memory Configuration */ //@ CMSMC = 0x00ff3e10; /* No V9 Cache/Shadow Memory Configuration */ //@ CMSMC = 0x00ff3e00; /* No V9 Cache/Shadow Memory Configuration */ //@ CMSMC = 0x00000e10; /* No V9 Cache/Shadow Memory Configuration */ diff --git a/SEL32/sel32_defs.h b/SEL32/sel32_defs.h index 36050f1..254eca1 100644 --- a/SEL32/sel32_defs.h +++ b/SEL32/sel32_defs.h @@ -231,6 +231,9 @@ typedef struct dib { uint32 chan_fifo[FIFO_SIZE]; /* interrupt status fifo for each channel */ } DIB; +extern DIB *dib_unit[MAX_DEV]; /* Pointer to Device info block */ +extern DIB *dib_chan[MAX_CHAN]; /* Pointer to channel mux dib */ + #define DEV_CHAN (1 << DEV_V_UF) /* Device is channel mux if set */ #define DEV_V_UF2 (DEV_V_UF+1) /* current usage */ diff --git a/SEL32/sel32_disk.c b/SEL32/sel32_disk.c index d74f39e..334c3a0 100644 --- a/SEL32/sel32_disk.c +++ b/SEL32/sel32_disk.c @@ -446,7 +446,6 @@ uint16 disk_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) uptr->CMDu3 |= DSK_INCH2; /* use 0xF0 for inch, just need int */ sim_activate(uptr, 20); /* start things off */ -//@41 sim_activate(uptr, 40); /* start things off */ return 0; break; @@ -461,49 +460,41 @@ uint16 disk_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) "disk_startcmd starting disk seek r/w cmd %02x chsa %04x\n", cmd, chsa); sim_activate(uptr, 20); /* start things off */ -//@41 sim_activate(uptr, 40); /* start things off */ -//@41 sim_activate(uptr, 250); /* start things off */ return 0; break; case DSK_NOP: /* NOP 0x03 */ uptr->CMDu3 |= cmd; /* save cmd */ sim_activate(uptr, 20); /* start things off */ -//@41 sim_activate(uptr, 40); /* start things off */ return 0; break; case DSK_SNS: /* Sense 0x04 */ uptr->CMDu3 |= cmd; /* save cmd */ sim_activate(uptr, 20); /* start things off */ -//@41 sim_activate(uptr, 40); /* start things off */ break; case DSK_WSL: /* WSL 0x31 */ uptr->CMDu3 |= cmd; /* save cmd */ sim_activate(uptr, 20); /* start things off */ -//@41 sim_activate(uptr, 40); /* start things off */ return 0; break; case DSK_RSL: /* RSL 0x32 */ uptr->CMDu3 |= cmd; /* save cmd */ sim_activate(uptr, 20); /* start things off */ -//@41 sim_activate(uptr, 40); /* start things off */ return 0; break; case DSK_WTL: /* WTL 0x51 */ uptr->CMDu3 |= cmd; /* save cmd */ sim_activate(uptr, 20); /* start things off */ -//@41 sim_activate(uptr, 40); /* start things off */ return 0; break; case DSK_RTL: /* RTL 0x52 */ uptr->CMDu3 |= cmd; /* save cmd */ sim_activate(uptr, 20); /* start things off */ -//@41 sim_activate(uptr, 40); /* start things off */ return 0; break; } @@ -514,7 +505,6 @@ uint16 disk_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) if (uptr->SNS & 0xff) /* any other cmd is error */ return SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK; sim_activate(uptr, 20); /* start things off */ -//@41sim_activate(uptr, 40); /* start things off */ return SNS_CHNEND|SNS_DEVEND; } @@ -558,8 +548,6 @@ t_stat disk_srv(UNIT *uptr) case DSK_INCH2: /* used 0xF0 for inch, just need int */ { uint32 mema; /* memory address */ -// uint32 daws[8]; /* drive attribute registers */ -// uint32 i, j; uint32 i; len = chp->ccw_count; /* INCH command count */ @@ -591,7 +579,6 @@ t_stat disk_srv(UNIT *uptr) /* the next 8 words have drive data for each unit */ /* WARNING 8 drives must be defined for this controller */ /* so we will not have a map fault */ -// for (i=0, j=0; i < 36; i++) { for (i=0; i < 36; i++) { if (chan_read_byte(chsa, &buf[i])) { /* we have error, bail out */ @@ -607,8 +594,6 @@ t_stat disk_srv(UNIT *uptr) (buf[2]<<8) | (buf[3]); else /* drive attribute registers */ - // daws[j++] = (buf[i-3]<<24) | (buf[i-2]<<16) - // | (buf[i-1]<<8) | (buf[i]); /* may want to use this later */ /* clear warning errors */ tstart = (buf[i-3]<<24) | (buf[i-2]<<16) @@ -630,11 +615,7 @@ t_stat disk_srv(UNIT *uptr) sim_debug(DEBUG_CMD, dptr, "disk_srv cmd INCH chsa %04x addr %06x count %04x completed\n", chsa, mema, chp->ccw_count); -#ifdef FIX4MPX - chan_end(chsa, SNS_CHNEND); /* return just channel end OK */ -#else chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* return OK */ -#endif } break; @@ -652,7 +633,6 @@ t_stat disk_srv(UNIT *uptr) /* we have write error, bail out */ uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */ chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); -//XXX goto goout; return SCPE_OK; break; } @@ -662,7 +642,6 @@ t_stat disk_srv(UNIT *uptr) } sim_debug(DEBUG_DETAIL, dptr, "\n"); chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* return OK */ -//XXXgoout: break; case DSK_WTL: /* WTL 0x51 make into NOP */ @@ -679,7 +658,6 @@ t_stat disk_srv(UNIT *uptr) uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */ chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); return SCPE_OK; -//XXX goto goout; break; } if (i == 16) @@ -741,7 +719,6 @@ t_stat disk_srv(UNIT *uptr) chan_write_byte(chsa, &ch); /* bytes 8-11 - drive mode register entries from assigned disk */ -//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); @@ -809,8 +786,6 @@ t_stat disk_srv(UNIT *uptr) unit, uptr->STAR >> 16, uptr->CHS >> 16); uptr->CHS = uptr->STAR; /* we are there */ sim_activate(uptr, 10); -//@41 sim_activate(uptr, 20); -//@41 sim_activate(uptr, 80); break; } } @@ -854,7 +829,6 @@ t_stat disk_srv(UNIT *uptr) sim_debug(DEBUG_CMD, dptr, "disk_srv STAR unit=%02x star %02x %02x %02x %02x\n", unit, buf[0], buf[1], buf[2], buf[3]); -//XXXrezero: sim_debug(DEBUG_DETAIL, dptr, "disk_srv seek unit=%02x star %02x %02x %02x %02x\n", unit, buf[0], buf[1], buf[2], buf[3]); @@ -913,7 +887,6 @@ t_stat disk_srv(UNIT *uptr) "disk_srv seeking unit=%02x to cyl %04x trk %02x sec %02x\n", unit, cyl, trk, buf[3]); sim_activate(uptr, 20); /* start us off */ -//@41 sim_activate(uptr, 30); /* start us off */ } else { /* we are on cylinder/track/sector, so go on */ sim_debug(DEBUG_DETAIL, dptr, @@ -978,14 +951,7 @@ t_stat disk_srv(UNIT *uptr) cyl = STAR2CYL(uptr->CHS); /* get current cyl */ trk = (uptr->CHS >> 8) & 0xff; /* get trk/head */ sec = uptr->CHS & 0xff; /* get sec */ -#ifdef DO_DYNAMIC_DEBUG - if (cyl == 0 && trk == 0 && sec == 8 && - chp->ccw_count == 0x2000 && chp->ccw_addr == 0x157c00) -// chp->ccw_count == 0x2000 && chp->ccw_addr == 0x1e7a40) - cpu_dev.dctrl |= (DEBUG_INST | DEBUG_CMD | DEBUG_EXP | DEBUG_IRQ); -#endif /* get sector offset */ -// tstart = STAR2SEC(uptr->STAR, SPT(type), SPC(type)); tstart = STAR2SEC(uptr->CHS, SPT(type), SPC(type)); sim_debug(DEBUG_CMD, dptr, @@ -1016,11 +982,7 @@ t_stat disk_srv(UNIT *uptr) uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */ chan_end(chsa, SNS_CHNEND|SNS_DEVEND); return SCPE_OK; -//XXX goto rddone; } -// sim_debug(DEBUG_DATA, dptr, -// "DISK Read2 %04x bytes leaving %04x from diskfile /%04x/%02x/%02x\n", -// i, chp->ccw_count, cyl, trk, sec); } sim_debug(DEBUG_CMD, dptr, @@ -1042,7 +1004,6 @@ t_stat disk_srv(UNIT *uptr) /* convert sect back to chs value */ uptr->CHS = disksec2star(tstart, type); /* see if over end of disk */ -// if (tstart >= CAPB(type)) { if (tstart >= (uint32)CAP(type)) { /* EOM reached, abort */ sim_debug(DEBUG_CMD, dptr, @@ -1058,7 +1019,6 @@ t_stat disk_srv(UNIT *uptr) "DISK sector read complete, %x bytes to go from diskfile /%04x/%02x/%02x\n", chp->ccw_count, STAR2CYL(uptr->CHS), ((uptr->CHS) >> 8)&0xff, (uptr->CHS&0xff)); sim_activate(uptr, 10); /* wait to read next sector */ -//@41 sim_activate(uptr, 30); /* wait to read next sector */ break; } break; @@ -1074,17 +1034,7 @@ t_stat disk_srv(UNIT *uptr) unit, uptr->CMDu3, chp->ccw_count, chp->ccw_addr, cyl, trk, sec); } if (uptr->CMDu3 & DSK_WRITING) { /* see if we are writing data */ -#ifdef DO_DYNAMIC_DEBUG - cyl = STAR2CYL(uptr->CHS); /* get current cyl */ - trk = (uptr->CHS >> 8) & 0xff; /* get trk/head */ - sec = uptr->CHS & 0xff; /* get sec */ - if (cyl == 10 && trk == 3 && sec == 0 && - chp->ccw_count == 0x2000 && chp->ccw_addr == 0x152800) -// chp->ccw_count == 0x2000 && chp->ccw_addr == 0x1e7a40) - cpu_dev.dctrl |= (DEBUG_INST | DEBUG_CMD | DEBUG_EXP | DEBUG_IRQ); -#endif /* get sector offset */ -// tstart = STAR2SEC(uptr->STAR, SPT(type), SPC(type)); tstart = STAR2SEC(uptr->CHS, SPT(type), SPC(type)); /* process the next sector of data */ @@ -1099,7 +1049,6 @@ t_stat disk_srv(UNIT *uptr) ssize, cyl, trk, sec); chan_end(chsa, SNS_CHNEND|SNS_DEVEND); return SCPE_OK; -//XXX goto wrdone; } ch = 0; /* finish out the sector with zero */ len++; /* show we have no more data to write */ @@ -1133,7 +1082,6 @@ t_stat disk_srv(UNIT *uptr) /* convert sect back to chs value */ uptr->CHS = disksec2star(tstart, type); /* see if over end of disk */ -// if (tstart >= CAPB(type)) { if (tstart >= (uint32)CAP(type)) { /* EOM reached, abort */ sim_debug(DEBUG_CMD, dptr, @@ -1145,7 +1093,6 @@ t_stat disk_srv(UNIT *uptr) break; } sim_activate(uptr, 10); /* keep writing */ -//@41 sim_activate(uptr, 30); /* keep writing */ break; } break; @@ -1297,7 +1244,6 @@ t_stat disk_srv(UNIT *uptr) cyl = disk_type[type].cyl-1; /* last cyl */ trk = disk_type[type].nhds-1; /* last head number */ -// sec = disk_type[type].spt-1; /* last sector number */ sim_debug(DEBUG_CMD, dptr, "disk_srv RTL STAR %04x/%02x/%02x Dmap pointer 0x%08x %d\n", @@ -1316,7 +1262,6 @@ t_stat disk_srv(UNIT *uptr) /* get sector address of umap table */ /* UMAP 249216 (819/15/0) 0x3cd80 for 9346 - 823/19/16 */ -//WAS tstart -= SPT(type); /* calc umap address */ tstart -= (2*SPT(type)); /* calc umap address */ /* the address must be physical for UDP/DPII */ @@ -1333,7 +1278,6 @@ 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; -//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; @@ -1364,7 +1308,6 @@ t_stat disk_srv(UNIT *uptr) sim_debug(DEBUG_CMD, dptr, "invalid command %02x unit %02x\n", cmd, unit); uptr->SNS |= SNS_CMDREJ; uptr->CMDu3 &= LMASK; /* remove old status bits & cmd */ -// chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); return SNS_CHNEND|STATUS_PCHK; break; } @@ -1423,18 +1366,14 @@ int disk_format(UNIT *uptr) { /* get sector address of utx diag map (DMAP) track 0 pointer */ /* put data = 0xf0000000 + (cyl-1), 0x8a000000 + daddr, */ /* 0x9a000000 + (cyl-1), 0xf4000008 */ -//WASint32 daddr = vaddr - SPT(type); int32 daddr = (CYL(type)-4) * SPC(type) + (HDS(type)-2) * SPT(type); /* get sector address of utx flaw data (1 track long) */ /* set trace data to zero */ -//WASint32 faddr = daddr - SPT(type); int32 faddr = (CYL(type)-4) * SPC(type) + (HDS(type)-3) * SPT(type); /* get sector address of utx flaw map sec 1 pointer */ /* use this address for sec 1 label pointer */ -//WASint32 uaddr = daddr - SPT(type); -//WASint32 uaddr = daddr - (2*SPT(type)); int32 uaddr = (CYL(type)-4) * SPC(type) + (HDS(type)-4) * SPT(type); /* last user block available */ @@ -1450,32 +1389,16 @@ int disk_format(UNIT *uptr) { 0,0x22c2813e,0,0x06020000,0xf4,0,0x431b1c,0, }; -#ifdef USE_FOR_MPX - { - /* some values created by j.vfmt */ -// 0xf003d14f,0x8a03cda0,0x9a03cdbf,0x8903cdc0, -// 0x9903d01f,0x8c03d020,0x9c03d14f,0xf4000000, - 0xf0000000 | (cap-1), 0x8a000000 | daddr, - 0x9a000000 | (daddr + ((2 * tsize) - 1)), - 0x89000000 | (daddr + (2 * tsize)), - 0x99000000 | ((cap-1)-spc), - 0x8c000000 | (cap-spc), - 0x9c000000 | (cap-1), 0xf4000000, - }; -#endif - /* vendor flaw map in vaddr */ uint32 vmap[2] = {0xf0000004, 0xf4000000}; /* defect map */ uint32 dmap[4] = {0xf0000000 | (cap-1), 0x8a000000 | daddr, 0x9a000000 | (cap-1), 0xf4000000}; -//TRY 0x9a000000 | (cap-1), 0xf4000008}; /* utx flaw map */ uint32 fmap[4] = {0xf0000000 | (cap-1), 0x8a000000 | daddr, 0x9a000000 | ltaddr, 0xf4000000}; -//TRY 0x9a000000 | ltaddr, 0xf4000008}; /* see if user wants to initialize the disk */ if (!get_yn("Initialize disk? [Y] ", TRUE)) { @@ -1645,6 +1568,7 @@ t_stat disk_attach(UNIT *uptr, CONST char *file) uint16 chsa = GET_UADDR(uptr->CMDu3); int type = GET_TYPE(uptr->flags); DEVICE *dptr = get_dev(uptr); + DIB *dibp = 0; t_stat r; uint32 ssize; /* sector size in bytes */ uint8 buff[1024]; @@ -1668,7 +1592,7 @@ t_stat disk_attach(UNIT *uptr, CONST char *file) if ((sim_fseek(uptr->fileref, 0, SEEK_SET)) != 0) { /* seek home */ detach_unit(uptr); /* if no space, error */ - return SCPE_FMT; /* error */ + return SCPE_UNATT; /* error */ } /* see if there is any data on sector zero of disk, if not format it */ @@ -1706,6 +1630,17 @@ fmt: sim_debug(DEBUG_CMD, dptr, "File %s attached to %s\r\n", file, disk_type[type].name); + /* check for valid configured disk */ + /* must have valid DIB and Channel Program pointer */ + dibp = (DIB *)dptr->ctxt; /* get the DIB pointer */ + if ((dib_unit[chsa] == NULL) || (dibp == NULL) || (dibp->chan_prg == NULL)) { + sim_debug(DEBUG_CMD, dptr, "ERROR===ERROR\nDISK device %s not configured on system, aborting\n", + dptr->name); + printf("ERROR===ERROR\nDISK device %s not configured on system, aborting\n", + dptr->name); + detach_unit(uptr); /* detach if error */ + return SCPE_UNATT; /* error */ + } set_devattn(chsa, SNS_DEVEND); return SCPE_OK; } diff --git a/SEL32/sel32_fltpt.c b/SEL32/sel32_fltpt.c index 1a8db2d..e21bb53 100644 --- a/SEL32/sel32_fltpt.c +++ b/SEL32/sel32_fltpt.c @@ -1,6 +1,7 @@ /* sel32_fltpt.c: SEL 32 floating point instructions processing. Copyright (c) 2018-2020, James C. Bevier + Portions provided by Richard Cornwell, Geert Rolf and other SIMH contributers Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -56,26 +57,31 @@ */ #include "sel32_defs.h" +#include uint32 s_fixw(uint32 val, uint32 *cc); uint32 s_fltw(uint32 val, uint32 *cc); + t_uint64 s_fixd(t_uint64 val, uint32 *cc); t_uint64 s_fltd(t_uint64 val, uint32 *cc); + uint32 s_nor(uint32 reg, uint32 *exp); t_uint64 s_nord(t_uint64 reg, uint32 *exp); -uint32 s_adfw(uint32 reg, uint32 mem, uint32 *cc); -uint32 s_sufw(uint32 reg, uint32 mem, uint32 *cc); -t_uint64 s_adfd(t_uint64 reg, t_uint64 mem, uint32 *cc); -t_uint64 s_sufd(t_uint64 reg, t_uint64 mem, uint32 *cc); + uint32 s_mpfw(uint32 reg, uint32 mem, uint32 *cc); uint32 s_dvfw(uint32 reg, uint32 mem, uint32 *cc); + +uint32 s_adfw(uint32 reg, uint32 mem, uint32 *cc); +uint32 s_sufw(uint32 reg, uint32 mem, uint32 *cc); + +t_uint64 s_adfd(t_uint64 reg, t_uint64 mem, uint32 *cc); +t_uint64 s_sufd(t_uint64 reg, t_uint64 mem, uint32 *cc); + 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); + +uint32 s_normfw(uint32 num, uint32 *cc); +t_uint64 s_normfd(t_uint64 num, uint32 *cc); #define NORMASK 0xf8000000 /* normalize 5 bit mask */ #define DNORMASK 0xf800000000000000ll /* double normalize 5 bit mask */ @@ -85,13 +91,31 @@ t_uint64 n_adfd(t_uint64 reg, t_uint64 mem, uint32 *cc, uint32 type); #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 +/************************************************************** +* Common routine for finishing the various F.P. instruction * +* * +* Floating point operations not terminating with an arith- * +* metic exception produce the following condition codes: * +* * +* CC1 CC2 CC3 CC4 Definition * +* ------------------------------------------------------- * +* 0 1 0 0 no exception, fraction positive * +* 0 0 1 0 no exception, fraction negative * +* 0 0 0 1 no exception, fraction = zero * +* * +* * +* an arithmetic exception produces the follwing condition * +* code settings: * +* * +* CC1 CC2 CC3 CC4 Definition * +* -------------------------------------------------------- * +* 1 0 1 0 exp underflow, fraction negative * +* 1 0 1 1 exp overflow, fraction negative * +* 1 1 0 0 exp underflow, fraction positive * +* 1 1 0 1 exp overflow, fraction positive * +* * +**************************************************************/ /* normalize floating point fraction */ uint32 s_nor(uint32 reg, uint32 *exp) { @@ -141,968 +165,223 @@ t_uint64 s_nord(t_uint64 reg, uint32 *exp) { return (reg); /* return normalized double register */ } -/************************************************************** -* This routine unpacks the floating point number in (r6,r7). * -* The unbiased, right justified, two's complement exponent * -* is returned in r1. If xxfw is set, the two's complement * -* fraction (with the binary point to the left of bit 8) is * -* returned in r6, and r7 is cleared. if xxfd is reset, the * -* 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 */ +/* normalize the memory value when adding number to zero */ +uint32 s_normfw(uint32 num, uint32 *cc) { + uint32 ret; + int32 val; /* temp word */ + int32 exp; /* exponent */ + int32 CCs; /* condition codes */ + uint8 sign; /* original sign */ -struct fpnum { - t_uint64 num; /* 64 bit number */ - int32 msw; /* most significent word */ - int32 lsw; /* least significient word */ + if (num == 0) { /* make sure we have a number */ + *cc = CC4BIT; /* set the cc's */ + return 0; /* return zero */ + } + sim_debug(DEBUG_EXP, &cpu_dev, + "NORMFW entry num %08x\n", num); + sign = 0; + + /* special case 0x80000000 (-0) to set CCs to 1011 * value to 0x80000001 */ + if (num == 0x80000000) { + CCs = CC1BIT|CC3BIT|CC4BIT; /* we have AE, exp overflow, neg frac */ + ret = 0x80000001; /* return max neg value */ + sim_debug(DEBUG_EXP, &cpu_dev, + "NORMFW AE return num %08x result %08x CC's %08x\n", num, ret, CCs); + /* return normalized number */ + *cc = CCs; /* set the cc's */ + return ret; /* return result */ + } + + /* special case pos exponent & zero mantissa to be 0 */ + if (((num & 0x80000000) == 0) && ((num & 0xff000000) > 0) && ((num & 0x00ffffff) == 0)) { + ret = 0; /* 0 to any power is still 0 */ + CCs = CC4BIT; /* set zero CC */ + sim_debug(DEBUG_EXP, &cpu_dev, + "NORMFW -ZERO num %08x result %08x CC's %08x\n", num, ret, CCs); + /* return normalized number */ + *cc = CCs; /* set the cc's */ + return ret; /* return result */ + } + + /* 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 ((num & 0x80ffffff) == 0x80000000) { + int nexp = (0x7f000000 & num) - 0x01000000; + num = 0x80000000 | (nexp & 0x7f000000) | 0x00f00000; + } + + exp = (num & 0x7f000000) >> 24; /* get exponent */ + if (num & 0x80000000) { /* test for neg */ + sign = 1; /* we are neq */ + num = NEGATE32(num); /* two's complement */ + exp ^= 0x7f; /* complement exponent */ + } + val = num & 0x00ffffff; /* get mantissa */ + + /* now make sure number is normalized */ + while ((val != 0) && ((val & 0x00f00000) == 0)) { + val <<= 4; /* move up a nibble */ + exp--; /* and decrease exponent */ + } + + if (exp < 0) { /* check for underflow */ + CCs = CC1BIT; /* we have underflow */ + if (sign & 1) /* we are neq */ + CCs |= CC3BIT; /* set neg CC */ + else + CCs |= CC2BIT; /* set pos CC */ + ret = 0; /* number too small, make 0 */ + exp = 0; /* exponent too */ + sim_debug(DEBUG_EXP, &cpu_dev, + "NORMFW UNDR return num %08x result %08x CC's %08x\n", num, ret, CCs); + /* return normalized number */ + *cc = CCs; /* set the cc's */ + return ret; /* return result */ + } + + /* rebuild normalized number */ + val = ((val & 0x00ffffff) | ((exp & 0x7f) << 24)); + if (sign & 1) /* we are neq */ + val = NEGATE32(val); /* two's complement */ + if (val == 0) + CCs = CC4BIT; /* show zero */ + else if (val & 0x80000000) /* neqative? */ + CCs = CC3BIT; /* show negative */ + else + CCs = CC2BIT; /* show positive */ + ret = val; /* return normalized number */ + sim_debug(DEBUG_EXP, &cpu_dev, + "NORMFW return num %08x result %08x CC's %08x\n", num, ret, CCs); + /* return normalized number */ + *cc = CCs; /* set the cc's */ + return ret; /* return result */ +} + +#ifdef FOR_DEBUG +/* sfpval - determine floating point data value */ +float sfpval(uint32 val) +{ + uint32 wd32; + float num; + int32 exp; + + exp = ((val >> 24) & 0x7f) - 0x40; /* get exponent and remove excess 0x40 */ + wd32 = val & 0x00ffffff; /* get mantissa */ + num = (float)wd32; /* make it a float */ + num *= exp2f((4*exp) - 24); /* raise to power of exponent */ + if (val & 0x80000000) + num *= -1.0; /* if negative, return negative num */ + return num; /* return value */ +} + +/* dfpval - determine double floating point data value */ +double dfpval(u_int64_t wd64) +{ + double dbl; + int32 exp; + u_int64_t sav = wd64; + + if (wd64 & 0x8000000000000000ll) + wd64 = NEGATE32(wd64); + exp = ((wd64 >> 56) & 0x7f) - 0x40; /* get exponent and remove excess 0x40 */ + wd64 &= 0x00ffffffffffffffll; /* get 56 bit mantissa */ + dbl = (double)wd64; /* make it a double float */ + dbl *= exp2((4*exp) - 56); /* raise to power of exponent */ + if (sav & 0x8000000000000000ll) + dbl *= -1.0; /* if negative, return negative num */ + return dbl; /* return value */ +} +#endif + +/* normalize the memory value when adding number to zero */ +t_uint64 s_normfd(t_uint64 num, uint32 *cc) { + t_uint64 ret; + t_uint64 val; /* temp word */ int32 exp; /* exponent */ int32 CCs; /* condition codes */ uint8 sign; /* original sign */ - uint8 flags; /* action flags for number */ -}; -/* unpack single precision floating point number */ -void unpacks(struct fpnum *np) { - uint32 ex = np->msw & 0xff000000; /* get exponent & sign from msw */ - - sim_debug(DEBUG_EXP, &cpu_dev, - "unpacks entry msw %08x exp %08x\n", np->msw, ex); - np->lsw = 0; /* 1 word for single precision */ -// ex = np->msw & 0xff000000; /* get exponent & sign from msw */ - if (ex & 0x80000000) /* check for negative */ - ex ^= 0xff000000; /* reset sign & complement exponent */ - np->msw ^= ex; /* replace exponent with sign extension */ - 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 */ - sim_debug(DEBUG_EXP, &cpu_dev, - "unpacks return msw %08x exp %08x\n", np->msw, ex); - return; -} - -/* unpack double precision floating point number */ -void unpackd(struct fpnum *np) { - int32 ex = np->msw & 0xff000000; /* get exponent & sign from msw */ - if (ex & 0x80000000) /* check for negative */ - ex ^= 0xff000000; /* reset sign & complement exponent */ - np->msw ^= ex; /* replace exponent with sign extension */ - 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 */ - return; -} - -/************************************************************** -* Common routine for finishing the various F.P. instruction * -* simulations. at this point, r1 = raw exponent, and * -* (r6,r7) = unnormalized fraction, with the binary point to * -* the left of r6[8]. The simulated condition codes will be * -* returned in bits 1 through 4 of "sim.flag." * -* * -* Floating point operations not terminating with an arith- * -* metic exception produce the following condition codes: * -* * -* CC1 CC2 CC3 CC4 Definition * -* ------------------------------------------------------- * -* 0 1 0 0 no exception, fraction positive * -* 0 0 1 0 no exception, fraction negative * -* 0 0 0 1 no exception, fraction = zero * -* * -* * -* an arithmetic exception produces the follwing condition * -* code settings: * -* * -* CC1 CC2 CC3 CC4 Definition * -* -------------------------------------------------------- * -* 1 0 1 0 exp underflow, fraction negative * -* 1 0 1 1 exp overflow, fraction negative * -* 1 1 0 0 exp underflow, fraction positive * -* 1 1 0 1 exp overflow, fraction positive * -* * -**************************************************************/ -/* Normalization and rounding of single precision number */ -void packs(struct fpnum *np) { - uint32 ex, tmp, tmp2; - - 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 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); - - if (num & DMSIGN) /* test for negative fraction */ - np->CCs = CC3BIT; /* show fraction negative */ - else - if (num == 0) { - np->CCs = CC4BIT; /* show fraction zero */ - np->msw = 0; /* save msw */ - np->lsw = 0; /* save lsw */ - np->exp = 0; /* save exp */ - return; /* done if zero */ - } - else - np->CCs = CC2BIT; /* show fraction positive */ - - sim_debug(DEBUG_EXP, &cpu_dev, - "pack pl 3 CC %08x num = %016llx ex = %08x\n", np->CCs, num, ex); - /* we need to round single precision number */ - tmp = (num >> 32) & 0xffffffff; /* get msw */ - tmp2 = num & 0xffffffff; /* get lsw */ - if ((int32)tmp >= 0x00ffffff) { /* if at max, no rounding */ - if (tmp2 & 0x80000000) /* round if set */ - tmp += 1; /* round fraction */ - } - num = (((t_uint64)tmp) << 32); /* make 64 bit num with lo 32 bits zero */ - - sim_debug(DEBUG_EXP, &cpu_dev, - "pack pl 4 num %016llx msw %08x exp %08x ex %08x\n", num, np->msw, np->exp, ex); - 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 */ - sim_debug(DEBUG_EXP, &cpu_dev, - "pack pl 4a num = %016llx exp = %08x ex = %08x\n", num, np->exp, ex); - } - /* end normalization and rounding */ - np->exp += ex; /* normalized, biased exp */ - np->exp += 1; /* correct shift count */ - - sim_debug(DEBUG_EXP, &cpu_dev, - "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; - } - sim_debug(DEBUG_EXP, &cpu_dev, - "pack exp num %016llx msw %08x exp %08x ex %08x\n", num, np->msw, np->exp, ex); - /* if no exponent overflow merge exp & fraction and return */ - if (((int32)(np->exp)) <= 0x7f) { - np->msw = (num >> 32); /* get msw */ - np->lsw = num & 0xffffffff; /* get lsw */ - sim_debug(DEBUG_EXP, &cpu_dev, - "packs ret msw %08x exp %08x\n", np->msw, np->exp); - ex = np->exp << 24; /* put exponent in bits 1-7 */ - sim_debug(DEBUG_EXP, &cpu_dev, - "packs ret msw %08x exp %08x ex %08x\n", np->msw, np->exp, ex); - np->msw ^= ex; /* merge exponent & fraction */ - sim_debug(DEBUG_EXP, &cpu_dev, - "packs ret CCs %08x msw %08x exp %08x ex %08x\n", np->CCs, np->msw, np->exp, ex); - return; /* CCs already set */ - } - /* process overflow exponent */ - np->CCs |= CC1BIT; /* set CC1 */ - np->CCs |= CC4BIT; /* set CC4 */ - /* do SP max value */ - if (np->CCs & CC2BIT) { /* see if CC2 is set */ - np->msw = 0x7fffffff; /* yes, use max pos value */ - np->lsw = 0; /* zero for SP */ - sim_debug(DEBUG_EXP, &cpu_dev, - "pack SP xit1 CCs %08x msw %08x exp %08x ex %08x\n", - np->CCs, np->msw, np->exp, ex); - return; - } - np->msw = 0x80000001; /* set max neg value */ - np->lsw = 0; /* zero for sp */ - sim_debug(DEBUG_EXP, &cpu_dev, - "pack SP xit2 CCs %08x msw %08x exp %08x ex %08x\n", - np->CCs, np->msw, np->exp, ex); - return; -} - -/** Normalization and rounding of double precision number */ -void packd(struct fpnum *np) { - uint32 ex; - - t_uint64 num = ((t_uint64)np->msw << 32) | np->lsw; /* make 64 bit num */ - - num = ((t_int64)num) << 3; /* sla 3 to align for normalization */ - num = s_nord(num, &ex); /* normalize the number with cnt in ex */ - num = ((t_int64)num) >> 7; /* align & sign extend number */ - if (num & DMSIGN) /* test for negative fraction */ - np->CCs = CC3BIT; /* show fraction negative */ - else - if (num == 0) { - np->CCs = CC4BIT; /* show fraction zero */ - np->msw = 0; /* save msw */ - np->lsw = 0; /* save lsw */ - np->exp = 0; /* save exp */ - return; /* done if zero */ - } - else - np->CCs = CC2BIT; /* show fraction positive */ - - if ((t_int64)num == DFSVAL) { /* see if > 0xff00000000000000 */ - num >>= 4; /* shift over 4 bits */ - ex += 1; /* bump exponent */ - } - /* end normalization and rounding */ - np->exp += ex; /* normalized, biased exp */ - 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; - } - /* if no exponent overflow merge exp & fraction & return */ - if (((int32)(np->exp)) <= 0x7f) { - np->msw = (num >> 32); /* get msw */ - np->lsw = num & 0xffffffff; /* get lsw */ - ex = np->exp << 24; /* put exponent in bits 1-7 */ - np->msw ^= ex; /* merge exponent & fraction */ - return; /* CCs already set */ - } - /* process overflow exponent */ - np->CCs |= CC1BIT; /* set CC1 & return zero */ - np->CCs |= CC4BIT; /* set CC4 & return zero */ - /* do DP max value */ - if (np->CCs & CC2BIT) { /* see if CC2 is set */ - np->msw = 0x7fffffff; /* CC2=1 set exp overflow, pos frac */ - np->lsw = 0xffffffff; - return; - } - np->msw = 0x80000000; /* CC2=0 set exp underflow, frac pos */ - np->lsw = 0x00000001; - return; -} - -/* normalize the memory value when adding number to zero */ -uint32 s_normfw(uint32 mem, uint32 *cc) { - struct fpnum fpn = {0}; - uint32 ret; - - if (mem == 0) { /* make sure we have a number */ + if (num == 0) { /* make sure we have a number */ *cc = CC4BIT; /* set the cc's */ return 0; /* return zero */ } 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); - /* return normalized number */ - *cc = fpn.CCs; /* set the cc's */ - return ret; /* return result */ -} - -/* 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; -#ifndef DO_NORMALIZE - struct fpnum fpn = {0}; -#endif - - *cc = 0; /* clear the CC'ss */ - CC = 0; /* clear local CC's */ - - sim_debug(DEBUG_EXP, &cpu_dev, - "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 */ -#ifndef DO_NORMALIZE - if (ret == 0) - goto goout; /* nothing + nothing = nothing */ - fpn.msw = ret; /* save upper 32 bits */ - fpn.lsw = 0; /* clear lower 32 bits */ - unpacks(&fpn); /* unpack number */ - packs(&fpn); /* pack it back up */ - 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 */ - expm ^= EXMASK; /* ones complement the exponent */ - mfrac |= EXMASK; /* adjust the fraction */ - } - mfrac = ((int32)mfrac) << 4; /* do sla 4 of fraction */ - - /* process the register operator value */ - if (reg == 0) { - 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 = ret; /* save upper 32 bits */ - fpn.lsw = 0; /* clear lower 32 bits */ - unpacks(&fpn); /* unpack number */ - packs(&fpn); /* pack it back up */ - 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 */ - expr ^= EXMASK; /* ones complement the exponent */ - rfrac |= EXMASK; /* adjust the fraction */ - } - rfrac = ((int32)rfrac) << 4; /* do sla 4 of fraction */ - - exp = expr - expm; /* subtract memory exponent from reg exponent */ - sim_debug(DEBUG_EXP, &cpu_dev, - "ADFW2 exp calc expr %04x expm %04x exp %04x\n", expr, expm, exp); - if (exp & MSIGN) { /* test for negative */ - /* difference is negative, so memory exponent is larger */ - exp = NEGATE32(exp); /* make difference positive */ - if (exp > 0x06000000) { /* test for difference > 6 */ - ret = mem; /* assume 0 and return original mem operand value */ - goto goout; /* go set cc's and return */ - } - /* difference is <= 6, so adjust to smaller value for add */ - /* difference is number of 4 bit right shifts to do */ - /* (exp >> 24) * 4 */ - 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 { - /* difference is zero or positive, so register exponent is larger */ - if (exp > 0x06000000) { /* test for difference > 6 */ - /* difference is > 6, so just act like add of zero */ - /* memory value is small, so return reg value as result */ - ret = reg; /* return original register value */ - goto goout; /* go set cc's and return */ - } - /* difference is <= 6, so adjust to smaller value for add */ - /* difference is number of 4 bit right shifts to do */ - /* (exp >> 24) * 4 */ - 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, - "ADFW3 after exp calc exp %04x sc %04x oexp %04x\n", exp, sc, oexp); - frac = rfrac + mfrac; /* add fractions */ - sim_debug(DEBUG_EXP, &cpu_dev, - "ADFW4 frac calc rfrac %06x mfrac %06x frac %04x\n", rfrac, mfrac, frac); - if (frac == 0) { - /* return the zero value */ - ret = frac; /* return zero to caller */ - goto goout; /* go set cc's and return */ - } - if ((int32)frac >= 0x10000000) { /* check for overflow */ - /* overflow */ - frac = ((int32)frac) >> 1; /* sra 1 */ - } else { - /* no overflow */ - /* check for underflow */ - if ((int32)frac >= 0xf0000000) { /* underflow? */ - frac = ((int32)frac) << 3; /* yes, sla 3 */ - oexp -= 0x01000000; /* adjust exponent */ - } else { - /* no underflow */ - frac = ((int32)frac) >> 1; /* sra 1 */ - } - } - /* normalize the frac value and put exponent into 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 */ - } - /* see if the exponent is normalized */ - if (exp == 0x40) { /* is result normalized? */ - /* normalized, so round */ - if (frac < 0x7fffffc0) /* check for special round */ - frac += 0x40; /* round mantissa */ - } else { - /* see if exponent and fraction are zero */ - if (exp == 0 && frac == 0) { - ret = 0; /* return zero */ - goto goout; /* go set cc's and return */ - } - } - 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 */ - sign = (oexp & MSIGN) != 0; /* get sign of largest exponent */ - sign |= ((exp & MSIGN) != 0) ? 2 : 0; /* get sign of nor exp */ - exp = exp + oexp; /* compute final exponent */ - if (exp & MSIGN) - /* we have exponent underflow if result is negative */ - goto ARUNFLO; - - /* if both signs are neg and result sign is positive, overflow */ - /* if both signs are pos and result sign is negative, overflow */ - if ((sign == 3 && (exp & MSIGN) == 0) || - (sign == 0 && (exp & MSIGN) != 0)) { - /* we have exponent overflow from addition */ -//AROVFLO: - CC |= CC4BIT; /* set CC4 for exponent overflow */ -ARUNFLO: - /* we have exponent underflow from addition */ - CC |= CC1BIT; /* set CC1 for arithmetic exception */ - ret = frac; /* get return value */ - if ((frac & MSIGN) == 0) { - CC |= CC2BIT; /* set pos fraction bit CC2 */ - } else { - 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: - return 0; /* pos underflow */ - break; - case 0x1: - return 0x7fffffff; /* positive overflow */ - break; - case 0x2: - return 0; /* neg underflow */ - break; - case 0x3: - 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 */ - } - /* come here to set cc's and return */ - /* ret has return value */ -goout: - if (ret & MSIGN) - CC |= CC3BIT; /* CC3 for neg */ - else if (ret == 0) - CC |= CC4BIT; /* CC4 for zero */ - else - CC |= CC2BIT; /* CC2 for greater than zero */ -goout2: - sim_debug(DEBUG_EXP, &cpu_dev, - "ADFW return mem %08x reg %08x result %08x CC %08x\n", mem, reg, ret, CC); - /* return temp to destination reg */ - *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) { - return s_adfw(reg, NEGATE32(mem), cc); -} - -/* normalize the memory value when adding number to zero */ -t_uint64 s_normfd(t_uint64 mem, uint32 *cc) { - struct fpnum fpn = {0}; - t_uint64 ret; - - if (mem == 0) { /* make sure we have a number */ - *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; + "NORMFD entry num %016llx\n", num); + 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 */ + if (num == 0x8000000000000000LL) { + CCs = CC1BIT|CC3BIT|CC4BIT; /* we have AE, exp overflow, neg frac */ ret = 0x8000000000000001LL; /* return max neg value */ - goto goret; /* return */ +// printf("NORMFD return num %016lx result %016lx CC's %08x\n", num, ret, CCs); + /* return normalized number */ + *cc = CCs; /* set the cc's */ + return ret; /* return normalized result */ } /* special case pos exponent & zero mantissa to be 0 */ - if (((mem & 0x8000000000000000LL) == 0) && ((mem & 0xff00000000000000LL) > 0) && - (mem & 0x00ffffffffffffffLL) == 0)) { + if (((num & 0x8000000000000000LL) == 0) && ((num & 0xff00000000000000LL) > 0) && + (num & 0x00ffffffffffffffLL) == 0) { ret = 0; /* 0 to any power is still 0 */ - fpn.CCs = CC4BIT; /* set zero CC */ - goto goret; /* return */ + CCs = CC4BIT; /* set zero CC */ + /* return normalized number */ + *cc = CCs; /* set the cc's */ + return ret; /* return normalized result */ } /* 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; + if ((num & 0x80ffffffffffffffLL) == 0x8000000000000000LL) { + t_uint64 nexp = (0x7f00000000000000LL & num) - 0x0100000000000000LL; + num = 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 */ + exp = (num & 0x7f00000000000000LL) >> 56; /* get exponent */ + if (num & 0x8000000000000000LL) { /* test for neg */ + sign = 1; /* we are neq */ + num = NEGATE32(num); /* two's complement */ + exp ^= 0x7f; /* complement exponent */ } - fpn.num = mem & 0x00ffffffffffffffLL; /* get mantissa */ + val = num & 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 */ + while ((val != 0) && ((val & 0x00f0000000000000LL) == 0)) { + val <<= 4; /* move up a nibble */ + 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 */ + + if (exp < 0) { + CCs = CC1BIT; /* we have underflow */ + if (sign & 1) /* we are neg */ + CCs |= CC3BIT; /* set neg CC */ else - fpn.CCs |= CC2BIT; /* set pos CC */ + CCs |= CC2BIT; /* set pos CC */ ret = 0; /* number too small, make 0 */ - goto goret; /* return */ + /* return normalized number */ + *cc = CCs; /* set the cc's */ + return ret; /* return normalized result */ } /* rebuild normalized number */ - ret = ((fpn.num & 0x00ffffffffffffff) | (((t_uint64)fpn.exp & 0x7f) << 56)); - if (fpn.sign & MEMNEG) /* we were neg (1) */ + ret = ((val & 0x00ffffffffffffffll) | (((t_uint64)exp & 0x7f) << 56)); + if (sign & 1) /* we were neg */ ret = NEGATE32(ret); /* two's complement */ if (ret == 0) - fpn.CCs = CC4BIT; /* show zero */ + CCs = CC4BIT; /* show zero */ else if (ret & 0x8000000000000000LL) /* neqative? */ - fpn.CCs = CC3BIT; /* show negative */ + CCs = CC3BIT; /* show negative */ else - fpn.CCs = CC2BIT; /* show positive */ -goret: -#endif -// ret = ((t_uint64)fpn.msw << 32) | fpn.lsw; /* make 64 bit num */ + CCs = CC2BIT; /* show positive */ sim_debug(DEBUG_EXP, &cpu_dev, - "NORMFD return mem %016llx result %016llx CC's %08x\n", mem, ret, fpn.CCs); + "NORMFD return num %016llx result %016llx CC's %08x\n", num, ret, CCs); /* return normalized number */ - *cc = fpn.CCs; /* set the cc's */ + *cc = CCs; /* set the cc's */ return ret; /* return normalized result */ } -/* 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) { -#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 */ - - 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 */ - } -//? 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 */ - } - - /* 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 */ - } -//? 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 */ - 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 */ - if (exp > 0x0d000000) { - /* shift count is > 13, so return operand and set cc's */ - ret = mem; /* return the original mem operand */ - goto goout; /* go set cc's and return */ - } - /* difference is <= 13, so adjust to smaller value for add */ - /* difference is number of 4 bit right shifts to do */ - /* (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 */ - } - else - { - /* exponent difference is zero or positive */ - if (exp > 0x0d000000) { - /* difference is > 13 */ - /* operand is small, so return reg value as result */ - ret = reg; /* get original reg value and return */ - goto goout; /* go set cc's and return */ - } - /* diff is <= 13, normalize */ - /* (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 */ - } - 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 = dfrac; /* return zero to caller */ - goto goout; /* go set cc's and return */ - } - 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 */ - dfrac = DNORMASK; /* correct the value */ - sc++; /* adjust exponent too */ - } - sc = (sc & 0xff) << 24; /* put nord exp in upper byte */ - sign = (exp & MSIGN) != 0; - sign |= ((sc & MSIGN) != 0) ? 2 : 0; - exp += sc; /* compute final exponent */ - /* if both signs are neg and result sign is positive, overflow */ - /* if both signs are pos and result sign is negative, overflow */ - if ((sign == 3 && (exp & MSIGN) == 0) || - (sign == 0 && (exp & MSIGN) != 0)) { - /* we have exponent overflow from addition */ - goto DOVFLO; - } - if (exp & MSIGN) - /* We have exponent underflow if result negative */ - goto DUNFLO; /* branch on underflow. */ - - 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 */ - /* fraction is negative */ - exp ^= EXMASK; /* neg fraction, so complement exponent */ - ret = ret | ((t_uint64)exp << 32); /* position and insert exponent */ - } - - /* come here to set cc's and return */ - /* dfrac 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: - 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 = dfrac; /* get return value */ - CC |= CC1BIT; /* set CC1 for arithmetic exception */ - 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) { - return s_adfd(reg, NEGATE32(mem), cc); -} - /* convert from 32 bit float to 32 bit integer */ /* set CC1 if overflow/underflow exception */ uint32 s_fixw(uint32 fltv, uint32 *cc) { @@ -1113,35 +392,49 @@ uint32 s_fixw(uint32 fltv, uint32 *cc) { fltv = NEGATE32(fltv); /* make src positive */ neg = 1; /* set neg val flag */ } else { - if (fltv == 0) { + if (fltv == 0) { /* value zero? */ temp = 0; /* return zero */ goto setcc; /* go set CC's */ } /* gt 0, fall through */ } - temp2 = (fltv >> 24); /* get exponent */ + temp2 = (uint32)(fltv >> 24); /* get exponent */ fltv <<= 8; /* move src to upper 3 bytes */ temp2 -= 64; /* take off excess notation */ - if ((int32)temp2 <= 0) { + temp = temp2; /* save val */ + if ((int32)temp2 == 0) /* exp of zero means zero */ + goto setcc; /* go set CC's */ + if (temp2 & MSIGN) { /* set CC1 for underflow */ - temp = 0; /* assume zero for small values */ - goto UNFLO; /* go set CC's */ + if (neg) { + temp = 0x7fffffff; /* too big, set to max value */ + goto OVFLO; /* go set CC's */ + } else { + temp = 0; /* assume zero for small values */ + goto UNFLO; /* go set CC's */ + } } + temp2 -= 8; /* see if in range */ + temp = fltv; /* save val */ + if ((temp2 == 0) && (fltv == 0x80000000) && (neg == 1)) + goto setcc; /* go set CC's */ if ((int32)temp2 > 0) { /* set CC1 for overflow */ - temp = 0x7fffffff; /* too big, set to max value */ + temp = 0; /* assume zero for small values */ goto OVFLO; /* go set CC's */ } sc = (NEGATE32(temp2) * 4); /* pos shift cnt * 4 */ fltv >>= sc; /* do 4 bit shifts */ + /* see if overflow to neg */ /* set CC1 for overflow */ if (fltv & MSIGN) { /* set CC1 for overflow */ - temp = 0x7fffffff; /* too big, set max */ + temp = 0; /* assume zero for small values */ goto OVFLO; /* go set CC's */ } + /* see if original value was negative */ if (neg) fltv = NEGATE32(fltv); /* put back to negative */ @@ -1201,6 +494,12 @@ uint32 s_fltw(uint32 intv, uint32 *cc) { sc >>= 2; /* normalize radix */ sc -= 72; /* make excess 64 notation */ sc = NEGATE32(sc); /* make positive */ + temp &= 0xffffff80; /* clean bits */ + if (neg) /* was input negative */ + temp += 0x80; /* round */ + else + temp += 0x80; /* round */ + temp = (temp >> 8) | (sc << 24); /* merge exp with fraction */ if (neg) /* was input negative */ temp = NEGATE32(temp); /* make neg again */ @@ -1221,12 +520,11 @@ 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; - int32 temp2, CC = 0, neg = 0, sc = 0; + uint32 temp2, CC = 0, neg = 0, sc = 0; t_uint64 dest; /* neg and CC flags already set to zero */ - if ((t_int64)dblv < 0) { + if (dblv & DMSIGN) { dblv = NEGATE32(dblv); /* make src positive */ neg = 1; /* set neg val flag */ } else { @@ -1236,33 +534,49 @@ t_uint64 s_fixd(t_uint64 dblv, uint32 *cc) { } /* gt 0, fall through */ } + temp2 = (uint32)(dblv >> 56); /* get exponent */ dblv <<= 8; /* move fraction to upper 7 bytes */ temp2 -= 64; /* take off excess notation */ - if ((int32)temp2 <= 0) { + dest = temp2; /* save val */ + if ((int32)temp2 == 0) /* zero exp means zero */ + goto dodblcc; /* go set CC's */ + if (temp2 & MSIGN) { /* set CC1 for underflow */ - dest = 0; /* assume zero for small values */ - goto DUNFLO; /* go set CC's */ + if (neg) { + dest = 0x7fffffffffffffff; /* too big, set to max value */ + goto DOVFLO; /* go set CC's */ + } else { + dest = 0; /* assume zero for small values */ + goto DUNFLO; /* go set CC's */ + } } + temp2 -= 16; /* see if in range */ + dest = dblv; /* save val */ + if ((temp2 == 0) && (dblv == DMSIGN) && (neg == 1)) + goto dodblcc; /* go set CC's */ if ((int32)temp2 > 0) { /* set CC1 for overflow */ - dest = 0x7fffffffffffffffll; /* too big, set max */ + dest = 0; /* assume zero for small values */ +// dest = 0x7fffffffffffffffll; /* too big, set max */ goto DOVFLO; /* go set CC's */ } sc = (NEGATE32(temp2) * 4); /* pos shift cnt * 4 */ dblv >>= sc; /* do 4 bit shifts */ + /* see if overflow to neg */ - /* FIXME set CC1 for overflow? */ if (dblv & DMSIGN) { /* set CC1 for overflow */ - dest = 0x7fffffffffffffffll; /* too big, set max */ + dest = 0; /* assume zero for small values */ +// dest = 0x7fffffffffffffffll; /* too big, set max */ goto DOVFLO; /* go set CC's */ } /* see if original values was negative */ if (neg) dblv = NEGATE32(dblv); /* put back to negative */ dest = dblv; /* return integer value */ + dodblcc: /* dest has return value */ if (dest & DMSIGN) @@ -1290,7 +604,8 @@ DUNFLO: /* convert from 64 bit integer to 64 bit double */ /* No overflow (CC1) can be generated */ t_uint64 s_fltd(t_uint64 intv, uint32 *cc) { - t_uint64 temp, sc = 0; /* zero shift count */ + t_uint64 temp; + int32 sc = 0; /* zero shift count */ uint32 neg = 0; /* zero sign flag */ uint32 CC = 0; /* n0 CC's yet */ @@ -1304,19 +619,20 @@ t_uint64 s_fltd(t_uint64 intv, uint32 *cc) { } /* gt 0, fall through */ } + if ((neg) && (intv & 0xfffffffffffffff0ll) && ((intv & 0x0fll))) + intv += 0x17ll; /* round */ temp = intv; /* get input t_uint64 */ - if ((temp & 0xff00000000000000ll) != 0) { - temp >>= 8; /* very large, make room for exponent */ - sc = -2; /* set exp count to 2 nibbles */ - } - while ((temp & 0x00f0000000000000ll) == 0) { /* see if normalized */ + while ((temp) && ((temp & 0xf000000000000000ll) == 0)) { /* see if normalized */ temp <<= 4; /* zero, shift in next nibble */ sc++; /* incr shift count */ } + temp >>= 8; /* make room for exponent */ + sc -= 2; /* adjust exp count */ sc = (NEGATE32(sc) + 78); /* normalized, make into excess 64 */ - temp = (sc << 56) | temp; /* merge exponent into fraction */ + temp = ((u_int64_t)sc << 56) | temp; /* merge exponent into fraction */ if (neg) /* was input negative */ temp = NEGATE32(temp); /* make neg again */ + /* come here to set cc's and return */ /* temp has return dbl value */ setcc: @@ -1331,6 +647,187 @@ setcc: return temp; /* return result */ } +#define CMASK 0x10000000 /* carry mask */ +#define EMASK 0x7f000000 /* single exponent mask */ +#define UMASK 0x0ffffff0 /* single fp mask */ +#define XMASK 0x0fffffff /* single fp mask */ +#define MMASK 0x00ffffff /* single mantissa mask */ +#define NMASK 0x0f000000 /* single nibble mask */ +#define ZMASK 0x00f00000 /* single nibble mask */ + +/* this new version is perfect against the diags, so good */ +/* do new SEL floating add derived from IBM370 code */ +/* Add/Sub single floating point */ +uint32 s_adfw(uint32 reg, uint32 mem, uint32 *cc) +{ + uint32 res, ret; + char sign = 0; + int er, em, temp; + uint32 CC; + + /* first we want to make sure the numbers are normalized */ + ret = s_normfw(reg, &CC); /* get the reg value */ + if (CC & CC1BIT) { /* see if we have AE */ + *cc = CC; /* save CC's */ + return ret; /* return results */ + } + reg = ret; /* use normalized value */ + if (mem == 0) { /* test for add of zero */ + *cc = CC; /* save CC's */ + return ret; /* return normalized results */ + } + + ret = s_normfw(mem, &CC); /* get the reg value */ + if (CC & CC1BIT) { /* see if we have AE */ + *cc = CC; /* save CC's */ + return ret; /* return results */ + } + mem = ret; /* use normalized value */ + if (reg == 0) { /* test for add to zero */ + *cc = CC; /* save CC's */ + return ret; /* return results results */ + } + + /* extract reg exponent and mantissa */ + if (reg & MSIGN) { /* reg negative */ + sign |= 2; /* set neg flag */ + reg = NEGATE32(reg); /* make negative positive */ + } + er = (reg & EMASK) >> 24; /* extract reg exponent */ + reg &= MMASK; /* extract reg mantissa */ + + /* extract mem exponent and mantissa */ + if (mem & MSIGN) { /* mem negative */ + sign |= 1; /* set neg flag */ + mem = NEGATE32(mem); /* make negative positive */ + } + em = (mem & EMASK) >> 24; /* extract mem exponent */ + mem &= MMASK; /* extract mem mantissa */ + + temp = er - em; /* get signed exp difference */ + mem = mem << 4; /* align mem for guard digit */ + reg = reg << 4; /* align reg for guard digit */ + + if (temp > 0) { /* reg exp > mem exp */ + if (temp > 8) { + mem = 0; /* if too much difference, make zero */ + } else { + /* Shift mem right if reg has larger exponent */ + while (temp-- != 0) { + mem >>= 4; /* adjust for exponent difference */ + em++; /* bump exponent */ + } + } + } else + if (temp < 0) { /* reg < mem exp */ + if (temp < -8) { + reg = 0; /* if too much difference, make zero */ + er = em; /* make exponents the same using mem exp */ + } else { + /* Shift reg right if mem has larger exponent */ + while (temp++ != 0) { + reg >>= 4; /* adjust for exponent difference */ + er++; /* bump exponent */ + } + } + } + + /* exponents should be equal now */ + /* add results */ + if (sign == 2 || sign == 1) { + /* different signs so do subtract */ + mem ^= XMASK; /* complement the value */ + mem++; /* increment the value */ + res = reg + mem; /* add the values */ + if (res & CMASK) { /* see if carry */ + res &= XMASK; /* clear off the carry bit */ + } else { + sign ^= 2; /* flip the sign */ + res ^= XMASK; /* and negate the value by comp */ + res++; /* incr */ + } + } else { + res = reg + mem; /* same sign, just add */ + if (sign == 3) + res += 7; /* round number */ +// res += 8; /* round number */ + } + + /* If overflow, shift right 4 bits */ + if (res & CMASK) { /* see if overflow carry */ + res >>= 4; /* move mantissa down 4 bits */ + er++; /* and adjust exponent */ + if (er >= 128) { /* if exponent too large, overflow */ + CC = CC1BIT|CC4BIT; /* set arithmetic overflow */ + /* OVERFLOW */ + /* set CC2 & CC3 on exit */ + CC |= (sign & 2)?CC3BIT:CC2BIT; /* neg is CC3, pos is CC2 */ + if (CC & CC3BIT) /* NEG overflow? */ + res = 0x80000001; /* yes */ + else + res = 0x7FFFFFFF; /* no, pos */ + /* Store result */ + *cc = CC; /* save CC's */ + return res; + } + } + + CC = 0; /* no CC's yet */ + /* Set condition codes */ + 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 */ + } + + /* normalize the fraction */ + if (CC != 0) { /* check for zero value */ + while ((res != 0) && ((res & NMASK) == 0)) { + res <<= 4; /* adjust mantisa by a nibble */ + er--; /* and adjust exponent smaller by 1 */ + } + /* Check if underflow */ + if (er < 0) { + /* UNDERFLOW */ + 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 */ + /* Store result */ + *cc = CC; /* save CC's */ + return res; /* return value */ + } + } else { + /* result is zero */ + sign = er = 0; /* make abs zero */ +// CC = CC4BIT; /* zero value */ + } + + res >>= 4; /* remove the guard nibble */ + + /* create result */ + res |= (er << 24) & EXMASK; /* combine exponent & mantissa */ + + /* set the CC's */ + if (CC == 0) { + CC = CC4BIT; /* zero value */ + } else { + if (sign & 2) + res = NEGATE32(res); /* make negative */ + CC = (CC & 3) << 28; /* neg is CC3, pos is CC2 */ + } + + *cc = CC; /* save CC's */ + return res; /* return result */ +} + +/* subtract memory floating point number from register floating point number */ +uint32 s_sufw(uint32 reg, uint32 mem, uint32 *cc) { + return s_adfw(reg, NEGATE32(mem), cc); +} + /* multiply register float by memory float, return float */ uint32 s_mpfw(uint32 reg, uint32 mem, uint32 *cc) { uint32 CC = 0, temp, temp2, sign; @@ -1381,13 +878,15 @@ uint32 s_mpfw(uint32 reg, uint32 mem, uint32 *cc) { /* temp has exponent from divide */ /* sign has final sign of result */ temp2 = (uint32)(dtemp >> 32); /* get upper 32 bits */ - if ((int32)temp2 >= 0x7fffffc0) /* check for special rounding */ - goto RRND2; /* no special handling */ if (temp2 == MSIGN) { /* check for minux zero */ temp2 = 0xF8000000; /* yes, fixup value */ expr++; /* bump exponent */ } + + if ((int32)temp2 >= 0x7fffffc0) /* check for special rounding */ + goto RRND2; /* no special handling */ + if (expr != 0x40) { /* result normalized? */ goto RRND2; /* if not, don't round */ } @@ -1494,7 +993,6 @@ uint32 s_dvfw(uint32 reg, uint32 mem, uint32 *cc) { reg >>= 6; /* adjust fraction for divide */ temp = expr - expm; /* subtract exponents */ -//BAD here temp = NEGATE32(temp); /* make reg positive */ dtemp = ((t_uint64)reg) << 32; /* put reg fraction in upper 32 bits */ temp2 = (uint32)(dtemp / mem); /* divide reg fraction by mem fraction */ temp2 >>= 3; /* shift out excess bits */ @@ -1590,302 +1088,6 @@ setcc: return temp; /* return result */ } -/* multiply register double by memory double */ -t_uint64 s_mpfd(t_uint64 reg, t_uint64 mem, uint32 *cc) { - t_uint64 tr1, tr2, tl1, tl2, dblreg; - uint32 CC = 0, temp = 0, temp2, sign = 0; - uint32 expm, expr; - t_uint64 dtemp1, dtemp2; - - /* process operator */ - if (mem & DMSIGN) { /* check for negative */ - mem = NEGATE32(mem); /* make mem positive */ - sign = 1; /* save original value for sign */ - } else { - if (mem == 0) { /* check for zero */ - dblreg = 0; /* we have zero operator */ - goto setcc; /* go set CC's */ - } - /* 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 */ - expm -= 0x40000000; /* adjust exponent bias */ - mem <<= 7; /* adjust fraction position */ - - /* process operand */ - if (reg & DMSIGN) { /* check for negative */ - sign ^= 1; /* adjust sign */ - reg = NEGATE32(reg); /* make reg positive */ - } else { - if (reg == 0) { - dblreg = 0; /* return zero */ - goto setcc; /* go set CC's */ - } - /* 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 */ - expr -= 0x40000000; /* adjust exponent bias */ - reg <<= 7; /* adjust fraction position */ - - temp = expr + expm; /* add exponents */ - - tl1 = (mem >> 32) & D32RMASK; /* get left half of operator */ - tr1 = mem & D32RMASK; /* get right half of operator */ - tl2 = (reg >> 32) & D32RMASK; /* get left half of operand */ - tr2 = reg & D32RMASK; /* get right half of operand */ - - dtemp2 = tl1 * (tr2 >> 1); /* operator left half * operand right half */ - dtemp2 <<= 1; /* readjust result */ - dtemp1 = tl2 * (tr1 >> 1); /* operand left half * operator right half */ - dtemp1 <<= 1; /* readjust result */ - dblreg = dtemp2 >> 32; /* save partial product */ - dtemp2 = tl2 * tl1; /* operand left half * operator left half */ - dtemp2 += dblreg; /* add partial product */ - dblreg = dtemp1 >> 32; /* save partial product */ - dtemp2 += dblreg; /* add other partial product */ - dblreg = (t_int64)dtemp2 << 1; /* position for normalize */ - if (sign) /* see if negative */ - dblreg = NEGATE32(dblreg); /* make negative */ - /* normalize the value in dblreg and put exponent into expr */ - dblreg = s_nord(dblreg, &expr); /* normalize fraction */ - if (expr != 0x40) /* is result normalized */ - dblreg &= 0xfffffffffffff87fll; /* no, adjust value */ - if (dblreg == DMSIGN) { /* check for neg zero */ - dblreg = DNORMASK; /* correct the value */ - expr++; /* adjust exponent too */ - } - expr <<= 24; /* reposition normalization count */ - temp2 = (expr & MSIGN) != 0; /* collect signs */ - temp2 |= ((temp & MSIGN) != 0) ? 2 : 0; - temp += expr; /* compute final exponent */ - /* if both signs are neg and result sign is positive, overflow */ - /* if both signs are pos and result sign is negative, overflow */ - if (((temp2 == 3) && ((temp & MSIGN) == 0)) || - ((temp2 == 0) && ((temp & MSIGN) != 0))) { - /* we have exponent overflow from addition */ - goto DOVFLO; /* process overflow */ - } - if (temp & MSIGN) /* see if negative */ - /* We have exponent underflow if result negative */ - 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 */ - } - goto setcc; /* go set CC's & exit */ - -DOVFLO: - CC |= CC4BIT; /* set CC4 for exponent overflow */ -DUNFLO: - CC |= CC1BIT; /* set CC1 for arithmetic exception */ - if (sign & MSIGN) /* test for negative */ - CC |= CC3BIT; /* set neg fraction bit CC3 */ - else - CC |= CC2BIT; /* set pos fraction bit CC2 */ - *cc = CC; /* return CC's */ - /* return value is not valid, but return fixup value anyway */ - switch ((CC >> 27) & 3) { /* rt justify CC3 & CC4 */ - case 0: - return 0; /* pos underflow */ - break; - case 1: - return 0x7fffffffffffffffll; /* positive overflow */ - break; - case 2: - return 0; /* neg underflow */ - break; - case 3: - return 0x8000000000000001ll; /* negative overflow */ - break; - } -setcc: - /* come here to set cc's and return */ - /* temp has return value */ - if (dblreg & DMSIGN) - CC |= CC3BIT; /* CC3 for neg */ - else if (temp == 0) - CC |= CC4BIT; /* CC4 for zero */ - else - CC |= CC2BIT; /* CC2 for greater than zero */ - *cc = CC; /* return CC's */ - return dblreg; /* return result */ -} - -/* divide register double by memory double */ -t_uint64 s_dvfd(t_uint64 reg, t_uint64 mem, uint32 *cc) { - t_uint64 tr1, /*tr2,*/ tl1, /*tl2,*/ dblreg; - uint32 CC = 0, temp, temp2, sign = 0; - uint32 expm, expr; - t_uint64 dtemp1, dtemp2; - - /* process operator */ - if (mem & DMSIGN) { /* check for negative */ - mem = NEGATE32(mem); /* make mem positive */ - sign = 1; /* save original value for sign */ - } else { - if (mem == 0) { /* check for divide by zero */ - goto DOVFLO; /* go process overflow */ - } - /* 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 */ - mem <<= 7; /* adjust fraction position */ - dtemp1 = mem & D32RMASK; /* get lower 32 bits */ - dtemp1 >>= 1; /* shift the rightmost 32 bits right 1 bit */ - mem = (mem & D32LMASK) | dtemp1; /* insert shifted value back into mem */ - - /* process operand */ - if (reg & DMSIGN) { /* check for negative */ - sign ^= 1; /* adjust sign */ - reg = NEGATE32(reg); /* make reg positive */ - } else { - if (reg == 0) { - dblreg = 0; /* return zero */ - goto setcc; /* go set CC's */ - } - /* 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 */ - - temp = expr - expm; /* subtract exponents */ - temp2 = (0x02000000 & MSIGN) != 0; /* collect signs */ - temp2 |= ((temp & MSIGN) != 0) ? 2 : 0; - temp += 0x02000000; /* adjust exponent (abr bit 6)*/ - /* if both signs are neg and result sign is positive, overflow */ - /* if both signs are pos and result sign is negative, overflow */ - if (((temp2 == 3) && ((temp & MSIGN) == 0)) || - ((temp2 == 0) && ((temp & MSIGN) != 0))) { - /* we have exponent overflow from addition */ - goto DOVFLO; /* process overflow */ - } - reg = ((t_int64)reg) >> 1; /* adjust fraction position */ - - tl1 = (mem >> 32) & D32RMASK; /* get left half of operator */ - tr1 = mem & D32RMASK; /* get right half of operator */ -// tl2 = (reg >> 32) & D32RMASK; /* get left half of operand */ -// tr2 = reg & D32RMASK; /* get right half of operand */ - - dtemp2 = reg / tl1; /* operand / left half of operator */ - dtemp2 = (dtemp2 & D32RMASK) << 32; /* move quotient to upper 32 bits */ - dtemp1 = reg % tl1; /* get remainder */ - dtemp1 = (dtemp1 & D32RMASK) << 32; /* move remainder to upper 32 bits */ - dtemp1 >>= 1; /* shift down by 1 */ - dtemp1 &= D32LMASK; /* make sure lower 32 bits are zero */ - - dtemp1 = dtemp1 / tl1; /* remainder / left half of operator */ - dtemp1 <<= 1; /* shift result back by 1 */ - dtemp1 &= D32RMASK; /* just lower 32 bits */ - dblreg = dtemp2 + dtemp1; /* sum of quotients */ - dtemp2 = dblreg >> 32; /* get upper 32 bits of sum */ - dblreg = ((t_int64)dblreg) >> 1; /* shift down sum */ - dtemp1 = tr1 * dtemp2; /* right half operator * (l opd/l opr) */ - dtemp1 = ((t_int64)dtemp1) >> 3; /* adjust sub total */ - dtemp1 = dtemp1 / tl1; /* r orp*(l opd/l opr)/l opr */ - dtemp1 = ((t_int64)dtemp1) << 3; /* adjust sub total */ - dblreg -= dtemp1; /* subtract from quotient */ - /* changing this mask by 2 bits gives mostly same result as real V6 */ - /* changed 04/20/20 */ -// dblreg &= 0xffffffffffffffe0; /* fixup quotient */ - dblreg &= 0xfffffffffffffff8; /* fixup quotient */ - /* exp in temp */ - if (sign) /* neg input */ - dblreg = NEGATE32(dblreg); /* yes, negate result */ - /* 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 */ - expr++; /* adjust exponent too */ - } - expr <<= 24; /* reposition normalization count */ - temp2 = (expr & MSIGN) != 0; /* collect signs */ - temp2 |= ((temp & MSIGN) != 0) ? 2 : 0; - temp += expr; /* compute final exponent */ - /* if both signs are neg and result sign is positive, overflow */ - /* if both signs are pos and result sign is negative, overflow */ - if ((temp2 == 3 && (temp & MSIGN) == 0) || - (temp2 == 0 && (expr & MSIGN) != 0)) { - /* we have exponent overflow from addition */ - goto DOVFLO; /* process overflow */ - } - if (temp & MSIGN) /* see if negative */ - /* We have exponent underflow if result is negative */ - 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 */ - } - goto setcc; /* go set CC's & exit */ - -DOVFLO: - CC |= CC4BIT; /* set CC4 for exponent overflow */ -DUNFLO: - CC |= CC1BIT; /* set CC1 for arithmetic exception */ - if (sign & MSIGN) /* test for negative */ - CC |= CC3BIT; /* set neg fraction bit CC3 */ - else - CC |= CC2BIT; /* set pos fraction bit CC2 */ - *cc = CC; /* return CC's */ - /* return value is not valid, but return fixup value anyway */ - /* Why not use an Array here? RPC */ -#if 0 - static retval[4] = { 0, MSIGN-1, 0, MSIGN}; /* At top of function */ - return retval[((CC >> 27) & 3]; -#endif - switch ((CC >> 27) & 3) { /* rt justify CC3 & CC4 */ - case 0: - return 0; /* pos underflow */ - break; - case 1: - return 0x7fffffffffffffffll; /* positive overflow */ - break; - case 2: - return 0; /* neg underflow */ - break; - case 3: - return 0x8000000000000001ll; /* negative overflow */ - break; - } -setcc: - /* come here to set cc's and return */ - /* temp has return value */ - if (dblreg & DMSIGN) - CC |= CC3BIT; /* CC3 for neg */ - else if (dblreg == 0) - CC |= CC4BIT; /* CC4 for zero */ - else - CC |= CC2BIT; /* CC2 for greater than zero */ - *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 */ @@ -1894,81 +1096,74 @@ setcc: #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 */ +/* this code creates an extra guard digit, so it is more accurate than SEL */ +/* The code was modified to have the same results as SEL, so we will use this one */ /* set CC1 if overflow/underflow */ -/* use revised normalization code */ -t_uint64 n_adfd(t_uint64 reg, t_uint64 mem, uint32 *cc, uint32 type) +t_uint64 s_adfd(t_uint64 reg, t_uint64 mem, uint32 *cc) { - u_int64_t res; + u_int64_t res, ret; uint8 sign = 0; int er, em, temp; - uint32 CC = 0; - - *cc = 0; /* clear the CC'ss */ + uint32 CC; sim_debug(DEBUG_EXP, &cpu_dev, "ADFD entry mem %016lx reg %016lx\n", mem, reg); + /* first we want to make sure the numbers are normalized */ + ret = s_normfd(reg, &CC); /* get the reg value */ + if (CC & CC1BIT) { /* see if we have AE */ + *cc = CC; /* save CC's */ + return ret; /* return results */ + } + reg = ret; /* use normalized value */ + if (mem == 0) { /* test for add of zero */ + *cc = CC; /* save CC's */ + return ret; /* return normalized results */ + } + + ret = s_normfd(mem, &CC); /* get the reg value */ + if (CC & CC1BIT) { /* see if we have AE */ + *cc = CC; /* save CC's */ + return ret; /* return results */ + } + mem = ret; /* use normalized value */ + if (reg == 0) { /* test for add to zero */ + *cc = CC; /* save CC's */ + return ret; /* return results results */ + } + /* 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 */ + sign |= 2; /* set neg flag */ + reg = NEGATE32(reg); /* make negative positive */ } -//#define DMMASK 0x00ffffffffffffffLL /* double mantissa mask */ - reg &= DMMASK; /* get reg mantissa */ + er = (reg & DEXMASK) >> 56; /* extract reg exponent */ + reg &= DMMASK; /* extract 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 */ - } + /* extract mem exponent and mantissa */ + if (mem & DMSIGN) { /* mem negative */ + sign |= 1; /* set neg flag */ + mem = NEGATE32(mem); /* make negative positive */ } + em = (mem & DEXMASK) >> 56; /* extract mem exponent */ + mem &= DMMASK; /* extract mem mantissa */ 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 */ + temp = er - em; /* get 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 */ + } else { + /* Shift mem right if reg has larger exponent */ 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 */ @@ -1977,75 +1172,65 @@ t_uint64 n_adfd(t_uint64 reg, t_uint64 mem, uint32 *cc, uint32 type) /* er now has equal exponent for both values */ /* add results */ -// if (sign == 2 || sign == 1) { - if (sign == REGNEG || sign == MEMNEG) { + if (sign == 2 || sign == 1) { /* 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) */ + sign ^= 2; /* flip the sign */ res ^= DIBMASK; /* and negate the value */ res++; /* negate all but the upper nibble */ } } else { res = reg + mem; /* same sign, just add */ + if ((res & 0x0fffffffffffff80ll) != 0x0fffffffffffff80ll) { + if (sign == 3) + res += 7; /* round number */ + if ((sign == 3) && (er == 0x7e)) + res |= 0x0f00ll; /* round number more */ + if (sign == 0) + res += 0xf; /* round number */ + } } + /* following statement effectively removes guard nibble to be like SEL */ + res &= 0xfffffffffffffff0ll; /* remove extra bits */ 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 */ + if (er >= 128) { /* 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 + if (CC & CC3BIT) /* NEG overflow? */ + res = 0x8000000000000001; /* double yes */ + else res = 0x7FFFFFFFFFFFFFFF; /* no, pos */ - goto goout; + /* store results */ + *cc = CC; /* save CC's */ + return res; /* return results */ } } -#ifdef MOVE + CC = 0; /* 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 */ - } + if (res != 0) /* see if non zero */ + CC |= (sign & 2) ? 1 : 2; + else { + er = sign = 0; /* we have zero CC4 */ } -#endif /* normalize the fraction */ - if (res != 0) { /* check for zero value */ + if (res != 0) { /* see if non zero */ while ((res != 0) && (res & DNMASK) == 0) { res <<= 4; /* adjust mantisa by a nibble */ er--; /* and adjust exponent smaller by 1 */ @@ -2058,154 +1243,97 @@ t_uint64 n_adfd(t_uint64 reg, t_uint64 mem, uint32 *cc, uint32 type) 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; + /* store results */ + *cc = CC; /* save CC's */ + return res; /* return results */ } } 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 */ - } + if (CC == 0) { + CC = CC4BIT; /* set zero cc */ + } else { + if (sign & 2) /* see if negative */ + res = NEGATE32(res); /* make negative */ + CC = (CC & 3) << 28; /* neg is CC3, pos is CC2 */ } -#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 +/* subtract memory floating point number from register floating point number */ +t_uint64 s_sufd(t_uint64 reg, t_uint64 mem, uint32 *cc) { + return s_adfd(reg, NEGATE32(mem), cc); +} + /* 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; +t_uint64 s_mpfd(t_uint64 reg, t_uint64 mem, uint32 *cc) { + u_int64_t res, ret; + int sign = 0; + int lsb = 0; 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 */ + /* first we want to make sure the numbers are normalized */ + ret = s_normfd(reg, &CC); /* get the reg value */ + if (CC & CC1BIT) { /* see if we have AE */ + *cc = CC; /* save CC's */ + return ret; /* return results */ + } + reg = ret; /* use normalized value */ + + ret = s_normfd(mem, &CC); /* get the reg value */ + if (CC & CC1BIT) { /* see if we have AE */ + *cc = CC; /* save CC's */ + return ret; /* return results */ + } + mem = ret; /* use normalized value */ + + /* see if multiply by zero */ + if ((reg == 0ll) || (mem == 0ll)) { /* test for mult by zero */ + *cc = CC4BIT; /* set CC 4 for 0 */ + return 0ll; /* return results results */ + } + + /* extract reg exponent and mantissa */ 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 */ + sign ^= 1; /* set neg flag */ + reg = NEGATE32(reg); /* make negative positive */ } -//#define DMMASK 0x00ffffffffffffffLL /* double mantissa mask */ - reg &= DMMASK; /* get reg mantissa */ -// reg = reg << 4; /* align reg for normalization */ + if (reg & 0x1ll) /* test lsb */ + lsb = 1; /* reg is odd */ + er = (reg & DEXMASK) >> 56; /* extract reg exponent */ + reg &= DMMASK; /* extract reg 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 */ - } - } - - /* 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 */ - } + /* extract mem exponent and mantissa */ + if (mem & DMSIGN) { /* mem negative */ + sign ^= 1; /* set neg flag */ + mem = NEGATE32(mem); /* make negative positive */ } + if (mem & 0x1ll) /* test lsb */ + lsb = 1; /* reg is odd */ + em = (mem & DEXMASK) >> 56; /* extract mem exponent */ + mem &= DMMASK; /* extract mem mantissa */ 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++) { + for (temp = 0; temp < 56; temp++) { /* Add if we need too */ if (reg & 1) res += mem; @@ -2215,195 +1343,187 @@ t_uint64 n_mpfd(t_uint64 reg, t_uint64 mem, uint32 *cc) { } er++; /* adjust exp for extra nible shift */ + /* fix up some boundry conditions */ + if ((res >= 0x0010000000000000ll) && (sign == 1)) { + res += 0x1; + } + else + if ((res == 0x000FFFFFFFFFFFFFll) && (sign == 1) && (er != 1)) { + if (lsb == 0) + if ((er == 0x41) || (er == 0x81)) + er++; + else + res += 0x1ll; + } + /* 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 */ + CC |= (sign & 1)?CC3BIT:CC2BIT; /* neg is CC3, pos is CC2 */ + if (CC & CC3BIT) /* NEG overflow? */ + res = 0x8000000000000001ll; /* double yes */ + else + res = 0x7FFFFFFFFFFFFFFFll; /* no, pos */ + /* store results */ + *cc = CC; /* save CC's */ + return res; /* return results */ } } /* Align the results */ if (res != 0) { -//#define DZMASK 0x00f0000000000000LL /* double nibble mask */ - while ((res != 0) && (res & DZMASK) == 0) { + while ((res != 0) && (res & DNMASK) == 0) { res <<= 4; /* move over mantessa */ er--; /* reduce exponent cocunt by 1 */ + if ((res == 0x00FFFFFFFFFFFFF0ll) && (sign == 1)) { + if (lsb == 0) { + er--; + } + else { + res += 0x10ll; + } + } } - if (er < 0) { /* check if rxponent underflow */ + /* Check if overflow */ + if (er >= 128) { /* if exponent is too large, overflow */ + /* OVERFLOW */ + CC = CC1BIT|CC4BIT; /* set arithmetic exception */ + if (sign & 1) { + CC |= CC3BIT; /* neg CC */ + res = 0x8000000000000001ll; /* neg overflow 1011 */ + } else { + CC |= CC2BIT; /* pos CC */ + res = 0x7FFFFFFFFFFFFFFFll; /* pos overflow 1101 */ + } + /* store results */ + *cc = CC; /* save CC's */ + return res; /* return results */ + } + /* Check if underflow */ + if (er < 0) { /* UNDERFLOW */ res = 0; /* make return value zero */ - sign = er = 0; + CC = (sign & 1)?CC3BIT:CC2BIT; /* neg is CC3, pos is CC2 */ CC |= CC1BIT; /* set arithmetic exception */ - CC |= CC4BIT; /* set zero value CC */ + *cc = CC; /* save CC's */ + return res; /* return results */ } + res >>= 4; /* remove guard nibble */ } else { - er = sign = 0; - CC |= CC4BIT; /* set zero value CC */ + er = sign = 0; /* have real zero */ } -//#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 */ + if (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 = (sign & 1)?CC3BIT:CC2BIT; /* neg is CC3, pos is CC2 */ + else CC = CC4BIT; /* set zero cc */ - } + + /* return results */ *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; +t_uint64 s_dvfd(t_uint64 reg, t_uint64 mem, uint32 *cc) { + t_uint64 res, ret; + int sign = 0; + int sign2 = 0; + int lsb = 0; int er, em, temp; uint32 CC; - *cc = 0; /* clear the CC'ss */ - CC = 0; /* clear local CC's */ + sim_debug(DEBUG_EXP, &cpu_dev, + "DVFD entry reg %016lx mem %016lx\n", reg, mem); - 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 */ + /* first we want to make sure the numbers are normalized */ + ret = s_normfd(reg, &CC); /* get the reg value */ + if (CC & CC1BIT) { /* see if we have AE */ + *cc = CC; /* save CC's */ + return ret; /* return results */ } -//#define DMMASK 0x00ffffffffffffffLL /* double mantissa mask */ - mem &= DMMASK; /* get mem mantissa */ -// mem = mem << 4; /* align mem for normalization */ + reg = ret; /* use normalized value */ - /* process the register operand value */ - /* extract exponent and mantissa */ -//#define DEXMASK 0x7f00000000000000LL /* double exponent mask */ - er = (reg & DEXMASK) >> 56; /* extract reg exponent */ + ret = s_normfd(mem, &CC); /* get the reg value */ + if (CC & CC1BIT) { /* see if we have AE */ + *cc = CC; /* save CC's */ + return ret; /* return results */ + } + mem = ret; /* use normalized value */ + + /* see if divide by or into zero */ + if ((reg == 0ll) || (mem == 0ll)) { /* test for divide by zero */ + *cc = CC4BIT; /* set CC 4 for 0 */ + return 0ll; /* return results */ + } + + /* extract reg exponent and mantissa */ if (reg & DMSIGN) { /* reg negative */ - sign |= 2; /* set neg flag */ - reg = NEGATE32(reg); /* complement exp */ - er ^= 0x7f; /* complement exp */ + sign ^= 1; /* set neg flag */ + reg = NEGATE32(reg); /* make negative positive */ + sign2 |= 2; /* set neg flag */ } -//#define DMMASK 0x00ffffffffffffffLL /* double mantissa mask */ - reg &= DMMASK; /* get reg mantissa */ -// reg = reg << 4; /* align reg for normalization */ + if (reg & 0x1ll) /* test lsb */ + lsb = 1; /* reg is odd */ + er = (reg & DEXMASK) >> 56; /* extract reg exponent */ + reg &= DMMASK; /* extract reg mantissa */ -//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 */ - } + /* extract mem exponent and mantissa */ + if (mem & DMSIGN) { /* mem negative */ + sign ^= 1; /* set neg flag */ + mem = NEGATE32(mem); /* make negative positive */ + sign2 |= 1; /* set neg flag */ } -//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)); + if (mem & 0x1ll) /* test lsb */ + lsb = 1; /* reg is odd */ + em = (mem & DEXMASK) >> 56; /* extract mem exponent */ + mem &= DMMASK; /* extract mem mantissa */ er = er - em + 0x40; /* get the exp value */ - /* move left 1 nubble for divide */ -//? reg <<= 4; -//? mem <<= 4; + /* move left 1 nibble for divide */ + /* Shift numbers up 4 bits so as not to lose precision below */ + reg <<= 4; + mem <<= 4; - /* see if we need to adjust divisor if larger that dididend */ + /* see if we need to adjust divisor if larger that dividend */ 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; @@ -2416,101 +1536,108 @@ t_uint64 n_dvfd(t_uint64 reg, t_uint64 mem, uint32 *cc) { /* 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); + /* If .5 off, round, but do not cause carry overflow */ + if (((reg & DMSIGN) != 0) && (res != 0x00FFFFFFFFFFFFFFll)){ res++; } -#endif -//printf("DV aft mpy res %016lx er %02x\n\r",res, er); + + /* fix up some boundry condtions to make diags happy */ + if (res == 0x00FFFFFFFFFFFFF1ll) { + res += 0x0fll; /* round up by nibble */ + } + else + if (res == 0x00FFFFFFFFFFFFF8ll) { + res &= 0x0FFFFFFFFFFFFFC0ll; /* remove some extra bits */ + } + else + if (res == 0x00FFFFFFFFFFFFFFll) { + if (lsb == 0) { + res += 0x1ll; /* round up by bit to force carry */ + } else { + if (sign) { + if (sign2 == 1) { + res &= 0x00FFFFFFFFFFFFF0ll; /* clear last nibble */ + } else { + res += 0x1ll; /* round up by bit to for carry */ + } + } else { + if (sign2 == 3) { + res += 0x1ll; /* round up by bit to for carry */ + } else { + res &= 0x00FFFFFFFFFFFFF0ll; /* clear last nibble */ + } + } + } + } + /* diags should be happy now */ /* 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 */ + if (er >= 128) { /* if exponent is too large, overflow */ /* OVERFLOW */ - res = 0x7fffffffffffffffll; /* too big, set max */ - CC = CC1BIT; /* set arithmetic exception */ + CC = CC1BIT|CC4BIT; /* set arithmetic exception */ + CC |= (sign & 1)?CC3BIT:CC2BIT; /* neg is CC3, pos is CC2 */ + if (CC & CC3BIT) /* NEG overflow? */ + res = 0x8000000000000001ll; /* double yes */ + else + res = 0x7FFFFFFFFFFFFFFFll; /* no, pos */ + /* store results */ + *cc = CC; /* save CC's */ + return res; /* return results */ } } /* Align the results */ if ((res) != 0) { -//#define DZMASK 0x00f0000000000000LL /* double nibble mask */ - while ((res & DZMASK) == 0) { + while ((res != 0) && (res & DZMASK) == 0) { res <<= 4; er--; } + /* Check if overflow */ + if (er >= 128) { /* if exponent is too large, overflow */ + /* OVERFLOW */ + CC = CC1BIT|CC4BIT; /* set arithmetic exception */ + if (sign & 1) { + CC |= CC3BIT; + res = 0x8000000000000001ll; /* neg overflow 1011 */ + } else { + CC |= CC2BIT; + res = 0x7FFFFFFFFFFFFFFFll; /* pos overflow 1101 */ + } + /* store results */ + *cc = CC; /* save CC's */ + return res; /* return results */ + } /* Check if underflow */ if (er < 0) { /* UNDERFLOW */ res = 0; /* make return value zero */ - sign = er = 0; + CC = (sign & 1)?CC3BIT:CC2BIT; /* neg is CC3, pos is CC2 */ CC |= CC1BIT; /* set arithmetic exception */ - CC |= CC4BIT; /* set zero value CC */ + *cc = CC; /* save CC's */ + return res; /* return results */ } } 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 &= DMMASK; /* clear exponent space */ + res |= ((((t_uint64)er) << 56) & DEXMASK); /* merge exp and mantissa */ - if (sign == 2 || sign == 1) /* is result to be negative */ + if (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 = (sign & 1)?CC3BIT:CC2BIT; /* neg is CC3, pos is CC2 */ + else CC = CC4BIT; /* set zero cc */ - } + + /* return results */ *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 diff --git a/SEL32/sel32_hsdp.c b/SEL32/sel32_hsdp.c index d24d524..30475bc 100644 --- a/SEL32/sel32_hsdp.c +++ b/SEL32/sel32_hsdp.c @@ -578,13 +578,9 @@ t_stat hsdp_srv(UNIT *uptr) DEVICE *dptr = get_dev(uptr); DIB *dibp = (DIB *)dptr->ctxt; /* get DIB address */ CHANP *chp = (CHANP *)dibp->chan_prg; /* get pointer to channel program */ -#ifdef OLDWAY - struct ddata_t *data = (struct ddata_t *)(uptr->DDATA); -#endif int cmd = uptr->CMD & DSK_CMDMSK; int type = GET_TYPE(uptr->flags); uint32 trk, cyl, sec; -// uint32 trk, cyl; int unit = (uptr - dptr->units); int len; int i; @@ -596,7 +592,6 @@ t_stat hsdp_srv(UNIT *uptr) sim_debug(DEBUG_CMD, dptr, "hsdp_srv entry unit %02x CMD %08x chsa %04x count %04x %x/%x/%x \n", -// unit, uptr->CMD, chsa, chp->ccw_count, data->cyl, data->tpos, data->spos); unit, uptr->CMD, chsa, chp->ccw_count, STAR2CYL(uptr->CHS), (uptr->CHS >> 8)&0xff, (uptr->CHS&0xff)); @@ -616,8 +611,6 @@ t_stat hsdp_srv(UNIT *uptr) case DSK_INCH2: /* use 0xc0 for inch, just need int */ { uint32 mema; /* memory address */ -// uint32 daws[8]; /* drive attribute registers */ -// uint32 i, j; uint32 i; len = chp->ccw_count; /* INCH command count */ @@ -649,7 +642,6 @@ t_stat hsdp_srv(UNIT *uptr) /* the next 8 words have drive data for each unit */ /* WARNING 8 drives must be defined for this controller */ /* so we will not have a map fault */ -// for (i=0, j=0; i < 36; i++) { for (i=0; i < 36; i++) { if (chan_read_byte(chsa, &buf[i])) { /* we have error, bail out */ @@ -665,8 +657,6 @@ t_stat hsdp_srv(UNIT *uptr) (buf[2]<<8) | (buf[3]); else /* drive attribute registers */ -// daws[j++] = (buf[i-3]<<24) | (buf[i-2]<<16) -// | (buf[i-1]<<8) | (buf[i]); /* may want to use this later */ /* clear warning errors */ tstart = (buf[i-3]<<24) | (buf[i-2]<<16) @@ -688,11 +678,7 @@ t_stat hsdp_srv(UNIT *uptr) sim_debug(DEBUG_CMD, dptr, "hsdp_srv cmd INCH chsa %04x addr %06x count %04x completed\n", chsa, mema, chp->ccw_count); -#ifdef FIX4MPX - chan_end(chsa, SNS_CHNEND); /* return just channel end OK */ -#else chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* return OK */ -#endif } break; @@ -1049,27 +1035,6 @@ goout: "hsdp_srv after READ chsa %04x buffer %06x count %04x\n", chsa, chp->ccw_addr, chp->ccw_count); -#ifdef LOOK - /* check for 0x280 or 0x308 read count */ - sec = chp->ccw_count; - if (sec == 0x308 || sec == 0x280) { - for (i = 0; i < sec; i++) { - if ((i%16) == 0) - sim_debug(DEBUG_CMD, dptr, "\nREAD: %06x", chp->ccw_addr + i); - sim_debug(DEBUG_CMD, dptr, " %02x", buf[i]); - } - sim_debug(DEBUG_CMD, dptr, "\n\n"); - } - if (sec == 0x308 || sec == 0x280) { - for (i = sec; i < ssize; i++) { - if (((i-sec)%16) == 0) - sim_debug(DEBUG_CMD, dptr, "\nREAD: %06x", chp->ccw_addr + i - sec); - sim_debug(DEBUG_CMD, dptr, " %02x", buf[i]); - } - sim_debug(DEBUG_CMD, dptr, "\n"); - } -#endif - /* process the next sector of data */ for (i=0; iCHS = hsdpsec2star(tstart, type); /* see of over end of disk */ -// if (tstart >= CAPB(type)) { if (tstart >= (uint32)CAP(type)) { /* EOM reached, abort */ sim_debug(DEBUG_CMD, dptr, @@ -1135,15 +1099,8 @@ rddone: trk = (uptr->CHS >> 8) & 0xff; /* get trk/head */ sec = uptr->CHS & 0xff; /* get sec */ /* get sector offset */ -// tstart = STAR2SEC(uptr->STAR, SPT(type), SPC(type)); tstart = STAR2SEC(uptr->CHS, SPT(type), SPC(type)); -#ifdef LOOK - /* check for 0x280 or 0x308 read count */ - sec = chp->ccw_count; - tstart = chp->ccw_addr; -#endif - /* process the next sector of data */ len = 0; /* used here as a flag for short read */ for (i=0; iccw_addr; -#endif } -#ifdef LOOK - /* check for 0x280 or 0x308 read count */ -// sec = chp->ccw_count; - if (sec == 0x308 || sec == 0x280) { - for (i = 0; i < sec; i++) { - if ((i%16) == 0) - sim_debug(DEBUG_CMD, dptr, "\nWRIT: %06x", tstart + i); - sim_debug(DEBUG_CMD, dptr, " %02x", buf[i]); - } - sim_debug(DEBUG_CMD, dptr, "\n\n"); - } - if (sec == 0x308 || sec == 0x280) { - tstart = trk - (ssize-sec); - for (i = sec; i < ssize; i++) { - if (((i-sec)%16) == 0) - sim_debug(DEBUG_CMD, dptr, "\nWRIT: %06x", tstart + i - sec); - sim_debug(DEBUG_CMD, dptr, " %02x", buf[i]); - } - sim_debug(DEBUG_CMD, dptr, "\n"); - } -#endif - /* write the sector to disk */ if ((i=sim_fwrite(buf2, 1, ssize, uptr->fileref)) != ssize) { sim_debug(DEBUG_CMD, dptr, @@ -1208,22 +1140,12 @@ rddone: sim_debug(DEBUG_CMD, dptr, "DISK WR to sec end %04x bytes end %04x to diskfile cyl %04x hds %02x sec %02x\n", len, ssize, cyl, trk, sec); -#ifdef LOOK - sec = 0; - for (i = 0; i < ssize; i++) { - if ((i%16) == 0) - sim_debug(DEBUG_CMD, dptr, "\nWRIT %3x:", i); - sim_debug(DEBUG_CMD, dptr, " %02x", buf[i]); - } - sim_debug(DEBUG_CMD, dptr, "\n\n"); -#endif /* tstart has file offset in sectors */ tstart++; /* bump to next sector */ /* convert sect back to chs value */ uptr->CHS = hsdpsec2star(tstart, type); /* see of over end of disk */ -// if (tstart >= CAPB(type)) { if (tstart >= (uint32)CAP(type)) { /* EOM reached, abort */ sim_debug(DEBUG_CMD, dptr, @@ -1259,36 +1181,15 @@ wrdone: /* The UTX med map is pointed to by sector label 1 */ /* simulate pointers here, set wd[3] in label to VDT */ -#ifdef OLD - /* get physical sector address of media defect table */ - /* VDT 286935 (819/9/0) 0x460f5 for 8887 - 823/10/35 */ - /* MDT 286930 (819/8/0) 0x460d2 for 8887 - 823/10/35 Trk 0 ptr */ - /* DMAP 286895 (819/7/0) 0x460af for 8887 - 823/10/35 */ - /* UMAP 286860 (819/6/0) 0x4608c for 8887 - 823/10/35 */ -#else /* get physical sector address of media defect table */ /* VDT 286965 (819/9/0) 0x460f5 for 8887 - 823/10/35 */ -// /* MDT 286930 (819/8/0) 0x460d2 for 8887 - 823/10/35 Trk 0 ptr */ /* DMAP 286930 (819/8/0) 0x460d2 for 8887 - 823/10/35 Trk 0 ptr */ -// /* DMAP 286895 (819/7/0) 0x460af for 8887 - 823/10/35 */ /* UMAP 286895 (819/7/0) 0x460af for 8887 - 823/10/35 */ -// /* UMAP 286860 (819/6/0) 0x4608c for 8887 - 823/10/35 */ -#endif -#ifdef OLD + /* get logical sector address of media defect table */ /* VDT 278766 (819/9/0) 0x440ee for 8887 - 823/10/34 */ - /* MDT 278732 (819/8/0) 0x440cc for 8887 - 823/10/34 */ - /* DMAP 278698 (819/7/0) 0x440aa for 8887 - 823/10/34 */ - /* UMAP 278664 (819/6/0) 0x44088 for 8887 - 823/10/34 Sec 0 ptr */ -#else - /* get logical sector address of media defect table */ - /* VDT 278766 (819/9/0) 0x440ee for 8887 - 823/10/34 */ -// /* MDT 278732 (819/8/0) 0x440cc for 8887 - 823/10/34 */ /* DMAP 278732 (819/8/0) 0x440cc for 8887 - 823/10/34 */ -// /* DMAP 278698 (819/7/0) 0x440aa for 8887 - 823/10/34 */ /* UMAP 278698 (819/7/0) 0x440aa for 8887 - 823/10/34 Sec 0 ptr */ -// /* UMAP 278664 (819/6/0) 0x44088 for 8887 - 823/10/34 Sec 0 ptr */ -#endif sim_debug(DEBUG_CMD, dptr, "hsdp_startcmd RSL STAR %08x disk geom %08x\n", uptr->CHS, GEOM(type)); @@ -1306,15 +1207,9 @@ wrdone: unit, buf[0], buf[1], buf[2], buf[3]); /* get physical sector address of UMAP */ -#ifdef OLD - /* UMAP 286860 (819/6/0) 0x4608c for 8887 - 823/10/35 */ - tstart = ((CYL(type)-4) * SPC(type)) + - ((HDS(type)-4) * SPT(type)); -#else /* UMAP 278698 (819/7/0) 0x440aa for 8887 - 823/10/34 Sec 0 ptr */ tstart = ((CYL(type)-4) * SPC(type)) + ((HDS(type)-3) * (SPT(type))); -#endif /* get physical sector address of UMAP */ sim_debug(DEBUG_CMD, dptr, @@ -1323,11 +1218,7 @@ wrdone: /* on HSDP DMAP is in wd 3 on label 0 */ /* on HSDP UMAP is in wd 4 on label 1 */ -#ifdef OLD - /* UMAP 278664 (819/6/0) 0x44088 for 8887 - 823/10/34 Sec 0 ptr */ -#else /* UMAP 278698 (819/7/0) 0x440aa for 8887 - 823/10/34 Sec 0 ptr */ -#endif tstart = (tstart * (SPT(type)-1))/SPT(type); /* make logical */ /* the address must be logical for HSDP */ @@ -1337,12 +1228,11 @@ wrdone: buf[14] = (tstart >> 8) & 0xff; buf[15] = (tstart) & 0xff; -#ifndef NOTNOW buf[16] = (tstart >> 24) & 0xff; /* UMAP pointer too */ buf[17] = (tstart >> 16) & 0xff; buf[18] = (tstart >> 8) & 0xff; buf[19] = (tstart) & 0xff; -#endif + /* the tech doc shows the cyl/trk/sec data is in the first 4 bytes */ /* of the track label, BUT it is really in the configuration data */ /* area are too. That is where UTX looks. Byte 27 is sectors/track */ @@ -1424,13 +1314,6 @@ wrdone: /* The UTX media map is pointed to by sector label 1 */ /* simulate pointers here, set wd[3] in label to VDT */ -#ifdef OLD - /* get physical sector address of media defect table */ - /* VDT 286935 (819/9/0) 0x460f5 for 8887 - 823/10/35 */ - /* MDT 286930 (819/8/0) 0x460d2 for 8887 - 823/10/35 Trk 0 ptr */ - /* DMAP 286895 (819/7/0) 0x460af for 8887 - 823/10/35 */ - /* UMAP 286860 (819/6/0) 0x4608c for 8887 - 823/10/35 */ -#else /* get physical sector address of media defect table */ /* VDT 286965 (819/9/0) 0x460f5 for 8887 - 823/10/35 */ // /* MDT 286930 (819/8/0) 0x460d2 for 8887 - 823/10/35 Trk 0 ptr */ @@ -1438,14 +1321,6 @@ wrdone: // /* DMAP 286895 (819/7/0) 0x460af for 8887 - 823/10/35 */ /* UMAP 286895 (819/7/0) 0x460af for 8887 - 823/10/35 */ // /* UMAP 286860 (819/6/0) 0x4608c for 8887 - 823/10/35 */ -#endif -#ifdef OLD - /* get logical sector address of media defect table */ - /* VDT 278766 (819/9/0) 0x440ee for 8887 - 823/10/34 */ - /* MDT 278732 (819/8/0) 0x440cc for 8887 - 823/10/34 */ - /* DMAP 278698 (819/7/0) 0x440aa for 8887 - 823/10/34 */ - /* UMAP 278664 (819/6/0) 0x44088 for 8887 - 823/10/34 Sec 0 ptr */ -#else /* get logical sector address of media defect table */ /* VDT 278766 (819/9/0) 0x440ee for 8887 - 823/10/34 */ // /* MDT 278732 (819/8/0) 0x440cc for 8887 - 823/10/34 */ @@ -1453,7 +1328,6 @@ wrdone: // /* DMAP 278698 (819/7/0) 0x440aa for 8887 - 823/10/34 */ /* UMAP 278698 (819/7/0) 0x440aa for 8887 - 823/10/34 Sec 0 ptr */ // /* UMAP 278664 (819/6/0) 0x44088 for 8887 - 823/10/34 Sec 0 ptr */ -#endif tstart = (CYL(type)-4) * SPC(type) + (HDS(type)-2) * SPT(type); @@ -1482,7 +1356,6 @@ wrdone: /* get logical sector address of umap table */ /* UMAP 278664 (819/6/0) 0x44088 for 8887 - 823/10/34 Sec 0 ptr */ tstart -= SPT(type); /* calc utxfmap address */ -//BAD tstart -= (2*SPT(type)); /* calc umap address */ /* the address must be logical */ /* 286860 physical becomes 278664 logical */ @@ -1532,7 +1405,6 @@ wrdone: sim_debug(DEBUG_CMD, dptr, "invalid command %02x unit %02x\n", cmd, unit); uptr->SNS |= SNS_CMDREJ; uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ -// chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); return SNS_CHNEND|STATUS_PCHK; break; } @@ -1595,7 +1467,6 @@ int hsdp_format(UNIT *uptr) { int32 logda = daddr*(SPC(type)-1)/(SPC(type)); int32 uaddr = daddr - SPT(type); -//BADnt32 uaddr = daddr - (2*SPT(type)); /* last block available */ int32 luaddr = (CYL(type)-4) * SPC(type); @@ -1604,37 +1475,16 @@ int hsdp_format(UNIT *uptr) { /* get sector address of utx flaw data (1 track long) */ /* set trace data to zero */ -//NOint32 faddr = daddr - SPT(type); /* make up a UMAP with the partition for 8887 disk */ uint32 umap[256] = { -//WAS 0x4e554d50,(cap-1),luaddr-1,0,0,0,0,0xe10, 0x4e554d50,logla,logua-1,0,0,0,0,0xe10, -//WAS 0,0x5258,0,0x4e5c,0x3e,luaddr,0,0xd32c, 0,0x5258,0,0x4e5c,0x3e,logua,0,0xd32c, 0x79,0x187cc,0x118,0x14410,0x23f,0,0,0, 0,0x3821a2d6,0,0x1102000,0xf4,0,0,0, -// dec 0x4e554d50,(cap-1),luaddr-1,0,0,0,0,3600, -// dec 0,21080,0,20060,62,luaddr,0,54060, -// dec 121,100300,280,82960,575,0,0,0, -// dec 0,clocksecs,0,17833984,244,0,0,0, }; -#ifdef USEFORMPX - { - /* some values created by j.vfmt */ -// 0xf003d14f,0x8a03cda0,0x9a03cdbf,0x8903cdc0, -// 0x9903d01f,0x8c03d020,0x9c03d14f,0xf4000000, - 0xf0000000 | (cap-1), 0x8a000000 | daddr, - 0x9a000000 | (daddr + ((2 * tsize) - 1)), - 0x89000000 | (daddr + (2 * tsize)), - 0x99000000 | ((cap-1)-spc), - 0x8c000000 | (cap-spc), - 0x9c000000 | (cap-1), 0xf4000000, - }; -#endif - /* NULL vendor flaw map */ uint32 vmap[2] = {0xf0000004, 0xf4000000}; @@ -1643,27 +1493,12 @@ int hsdp_format(UNIT *uptr) { 0x9a000000 | (cap-1), 0xf4000008}; uint32 dmap[4] = {0xf0000000 | logla, 0x8a000000 | logda, 0x9a000000 | logla, 0xf4000008}; -//WAS 0x9a000000 | (cap-1), 0xf4000000}; /* see if user wants to initialize the disk */ if (!get_yn("Initialize disk? [Y] ", TRUE)) { return 1; } -#ifdef OLD_WAY - /* dmap data */ - /* the diag map (dmap) is in last sec of disk */ - /* (cyl * trk * sec) - 1 = cap - 1*/ - /* 0xf0046531 - 288049 - 822/9/34 */ - /* 0x8a0460d2 - 286930 - 819/8/0 */ - /* 0x9a046531 - 288049 - 822/9/34 */ - /* 0xf4000000 */ - dmap[0] = 0xf0000000 | (cap-1); /* 0xf003d14f */ - dmap[1] = 0x8a000000 | daddr; /* 0x8a03ccaf */ - dmap[2] = 0x9a000000 | (cap-1); /* 0x9a03d14f */ - dmap[3] = 0xf4000000; -#endif - /* get physical sector address of media defect table */ /* VDT 286965 (819/9/0) 0x460f5 for 8887 - 823/10/35 */ // /* MDT 286930 (819/8/0) 0x460d2 for 8887 - 823/10/35 Trk 0 ptr */ @@ -1786,22 +1621,6 @@ int hsdp_format(UNIT *uptr) { return 1; } -#ifdef NOTUSED - /* write dummy DMAP to faddr */ - if ((sim_fseek(uptr->fileref, faddr*ssize, SEEK_SET)) != 0) { /* seek DMAP */ - sim_debug(DEBUG_CMD, dptr, - "Error on media flaw map seek to sect %06x offset %06x\n", - faddr, faddr*ssize); - return 1; - } - if ((sim_fwrite((char *)&dmap, sizeof(uint32), 4, uptr->fileref)) != 4) { - sim_debug(DEBUG_CMD, dptr, - "Error writing flaw map to sect %06x offset %06x\n", - faddr, faddr*ssize); - return 1; - } -#endif - /* write UTX umap to uaddr */ if ((sim_fseek(uptr->fileref, uaddr*ssize, SEEK_SET)) != 0) { /* seek UMAP */ sim_debug(DEBUG_CMD, dptr, @@ -1818,10 +1637,6 @@ int hsdp_format(UNIT *uptr) { printf("writing to vmap sec %x (%d) bytes %x (%d)\n", vaddr, vaddr, (vaddr)*ssize, (vaddr)*ssize); -#ifdef NOTUSED - printf("writing to flaw map sec %x (%d) bytes %x (%d)\n", - faddr, faddr, (faddr)*ssize, (faddr)*ssize); -#endif printf("writing dmap to %x %d %x %d dmap to %x %d %x %d\n", cap-1, cap-1, (cap-1)*ssize, (cap-1)*ssize, daddr, daddr, daddr*ssize, daddr*ssize); @@ -1839,9 +1654,10 @@ int hsdp_format(UNIT *uptr) { /* attach the selected file to the disk */ t_stat hsdp_attach(UNIT *uptr, CONST char *file) { - uint16 addr = GET_UADDR(uptr->CMD); + uint16 chsa = GET_UADDR(uptr->CMD); int type = GET_TYPE(uptr->flags); DEVICE *dptr = get_dev(uptr); + DIB *dibp = 0; t_stat r; uint32 ssize; /* sector size in bytes */ uint8 buff[1024]; @@ -1903,7 +1719,19 @@ fmt: sim_debug(DEBUG_CMD, dptr, "File %s attached to %s\r\n", file, hsdp_type[type].name); - set_devattn(addr, SNS_DEVEND); + /* check for valid configured disk */ + /* must have valid DIB and Channel Program pointer */ + dibp = (DIB *)dptr->ctxt; /* get the DIB pointer */ + if ((dib_unit[chsa] == NULL) || (dibp == NULL) || (dibp->chan_prg == NULL)) { + sim_debug(DEBUG_CMD, dptr, + "ERROR===ERROR\nHSDP device %s not configured on system, aborting\n", + dptr->name); + printf("ERROR===ERROR\nHSDP device %s not configured on system, aborting\n", + dptr->name); + detach_unit(uptr); /* detach if error */ + return SCPE_UNATT; /* error */ + } + set_devattn(chsa, SNS_DEVEND); return SCPE_OK; } diff --git a/SEL32/sel32_iop.c b/SEL32/sel32_iop.c index 2f8c98e..75b6b92 100644 --- a/SEL32/sel32_iop.c +++ b/SEL32/sel32_iop.c @@ -35,7 +35,6 @@ #if NUM_DEVS_IOP > 0 -//#define UNIT_IOP UNIT_ATTABLE | UNIT_IDLE | UNIT_DISABLE #define UNIT_IOP UNIT_IDLE | UNIT_DISABLE /* forward definitions */ @@ -72,7 +71,6 @@ const char *iop_desc(DEVICE *dptr); #define SNS_ONLN 0x40 /* device online */ /* std devices. data structures - iop_dev Console device descriptor iop_unit Console unit descriptor iop_reg Console register list @@ -120,13 +118,10 @@ DIB iop_dib = { DEVICE iop_dev = { "IOP", iop_unit, NULL, iop_mod, NUM_UNITS_IOP, 8, 15, 1, 8, 8, - NULL, NULL, &iop_reset, /* examine, deposit, reset */ - NULL, NULL, NULL, /* boot, attach, detach */ + NULL, NULL, &iop_reset, /* examine, deposit, reset */ + NULL, NULL, NULL, /* boot, attach, detach */ /* dib ptr, dev flags, debug flags, debug */ -// &iop_dib, DEV_CHAN|DEV_DISABLE|DEV_DEBUG, 0, dev_debug, &iop_dib, DEV_CHAN|DEV_DIS|DEV_DISABLE|DEV_DEBUG, 0, dev_debug, -// NULL, NULL, &iop_help, /* ?, ?, help */ -// NULL, NULL, &iop_desc /* ?, ?, description */ }; /* IOP controller routines */ @@ -165,11 +160,9 @@ uint16 iop_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) iop_chp[0].chan_inch_addr); /* set inch buffer addr */ iop_chp[0].chan_inch_addr = iop_chp[0].ccw_addr; /* set inch buffer addr */ -// set_inch(uptr, iop_chp[0].ccw_addr); /* new address */ uptr->u3 |= IOP_INCH2; /* save INCH command as 0xf0 */ - sim_activate(uptr, 20); /* go on */ -//@41 sim_activate(uptr, 40); /* go on */ + sim_activate(uptr, 40); /* go on */ return 0; /* no status change */ break; @@ -178,8 +171,7 @@ uint16 iop_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) uptr->u5 = SNS_RDY|SNS_ONLN; /* status is online & ready */ uptr->u3 &= LMASK; /* leave only chsa */ uptr->u3 |= (cmd & IOP_MSK); /* save NOP command */ - sim_activate(uptr, 20); /* TRY 07-13-19 */ -//@41 sim_activate(uptr, 40); /* TRY 07-13-19 */ + sim_activate(uptr, 40); /* TRY 07-13-19 */ return 0; /* no status change */ break; @@ -189,8 +181,7 @@ uint16 iop_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) chan, cmd, uptr->u5); uptr->u3 &= LMASK; /* leave only chsa */ uptr->u3 |= (cmd & IOP_MSK); /* save command */ - sim_activate(uptr, 20); /* force interrupt */ -//@41 sim_activate(uptr, 40); /* force interrupt */ + sim_activate(uptr, 40); /* force interrupt */ return 0; /* no status change */ break; } @@ -203,10 +194,7 @@ t_stat iop_srv(UNIT *uptr) { uint16 chsa = GET_UADDR(uptr->u3); int cmd = uptr->u3 & IOP_MSK; -// CHANP *chp = find_chanp_ptr(chsa); /* find the chanp pointer */ CHANP *chp = &iop_chp[0]; /* find the chanp pointer */ -// int i; -// int len = chp->ccw_count; /* INCH command count */ uint32 mema = chp->ccw_addr; /* get inch or buffer addr */ /* test for NOP or INCH cmds */ @@ -233,12 +221,9 @@ t_stat iop_srv(UNIT *uptr) /* the chp->ccw_addr location contains the inch address */ /* call set_inch() to setup inch buffer */ -// i = set_inch(uptr, mema); /* new address */ set_inch(uptr, mema); /* new address */ -// chp->chan_inch_addr = mema; /* set inch buffer addr */ uptr->u3 &= LMASK; /* clear the cmd */ chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* we are done dev|chan end */ -// chan_end(chsa, SNS_CHNEND); /* we are done dev|chan end */ } return SCPE_OK; } @@ -256,8 +241,6 @@ t_stat iop_help(FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, CONST char *cptr fprintf(st, "The IOP fields all interrupts and status posting\r\n"); fprintf(st, "for each of the controllers on the system.\r\n"); fprintf(st, "Nothing can be configured for this Channel.\r\n"); -// fprint_set_help(st, dptr); -// fprint_show_help(st, dptr); return SCPE_OK; } diff --git a/SEL32/sel32_lpr.c b/SEL32/sel32_lpr.c index f7fae76..c37ade9 100644 --- a/SEL32/sel32_lpr.c +++ b/SEL32/sel32_lpr.c @@ -66,18 +66,19 @@ LP.CMD17 DATAW X'37000000' (SPARE) ** LINE PRINTER FORMS CONTROL TABLE * LPFCTBL EQU $ -P0006C 2B DATAB C'+' 0x2b FORMS CONTROL FOR CR THEN PRINT -P0006D 31 DATAB C'1' 0x31 FORMS CONTROL FOR FF THEN PRINT -P0006E 2D DATAB C'-' 0x2d FORMS CONTROL FOR FF THEN PRINT -P0006F 30 DATAB C'0' 0x30 FORMS CONTROL FOR 2 LF'S THEN PRINT -P00070 20 DATAB C' ' 0x20 FORMS CONTROL FOR LF THEN PRINT + 2B DATAB C'+' 0x2b FORMS CONTROL FOR CR THEN PRINT + 31 DATAB C'1' 0x31 FORMS CONTROL FOR FF THEN PRINT + 2D DATAB C'-' 0x2d FORMS CONTROL FOR FF THEN PRINT + 30 DATAB C'0' 0x30 FORMS CONTROL FOR 2 LF'S THEN PRINT + 20 DATAB C' ' 0x20 FORMS CONTROL FOR LF THEN PRINT */ #if NUM_DEVS_LPR > 0 -//#define UNIT_LPR UNIT_ATTABLE | UNIT_IDLE | UNIT_DISABLE -#define UNIT_LPR UNIT_ATTABLE | UNIT_IDLE +#define UNIT_LPR UNIT_ATTABLE | UNIT_IDLE | UNIT_DISABLE +//#define UNIT_LPR UNIT_ATTABLE | UNIT_IDLE +#define CMDu3 u3 /* u3 hold command and status information */ #define LPR_INCH 0x00 /* INCH command */ /* print buffer then CC commands */ @@ -107,7 +108,10 @@ P00070 20 DATAB C' ' 0x20 FORMS CONTROL FO #define LPR_PRE 0x200 /* Apply pre CC */ #define LPR_POST 0x400 /* Apply post CC */ -/* u4 holds current line */ +#define CNTu4 u4 +/* u4 holds current line count */ + +#define SNSu5 u5 /* in u5 packs sense byte 0,1 and 3 */ /* Sense byte 0 */ #define SNS_CMDREJ 0x80 /* Command reject */ @@ -118,6 +122,8 @@ P00070 20 DATAB C' ' 0x20 FORMS CONTROL FO #define SNS_OVRRUN 0x04 /* Data overrun */ #define SNS_SEQUENCE 0x02 /* Unusual sequence */ #define SNS_BOF 0x01 /* BOF on printer */ + +#define CBPu6 u6 /* u6 hold buffer position */ /* std devices. data structures @@ -129,7 +135,7 @@ P00070 20 DATAB C' ' 0x20 FORMS CONTROL FO struct _lpr_data { - uint8 lbuff[160]; /* Output line buffer */ + uint8 lbuff[160]; /* Output line buffer */ } lpr_data[NUM_DEVS_LPR]; @@ -185,8 +191,8 @@ DEVICE lpr_dev = { NUM_DEVS_LPR, 8, 15, 1, 8, 8, NULL, NULL, NULL, NULL, &lpr_attach, &lpr_detach, /* ctxt is the DIB pointer */ -// &lpr_dib, DEV_DIS|DEV_DISABLE|DEV_DEBUG, 0, dev_debug - &lpr_dib, DEV_DISABLE | DEV_DEBUG, 0, dev_debug + &lpr_dib, DEV_DISABLE|DEV_DEBUG, 0, dev_debug +// &lpr_dib, DEV_DISABLE|DEV_DEBUG|DEV_DIS, 0, dev_debug }; /* initialize the line printer */ @@ -197,16 +203,16 @@ void lpr_ini(UNIT *uptr, t_bool f) { /* start an I/O operation */ uint16 lpr_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) { - if ((uptr->u3 & LPR_CMDMSK) != 0) { /* unit busy */ + if ((uptr->CMDu3 & LPR_CMDMSK) != 0) { /* unit busy */ return SNS_BSY; /* yes, busy (already tested) */ } - uptr->u3 &= ~(LPR_POST|LPR_PRE); /* set no CC */ + uptr->CMDu3 &= ~(LPR_POST|LPR_PRE); /* set no CC */ if (((cmd & 0x03) == 0x03) || (cmd & 0x0f) == 0x0d) { - uptr->u3 |= LPR_PRE; /* apply pre CC */ + uptr->CMDu3 |= LPR_PRE; /* apply pre CC */ } if (((cmd & 0x0f) == 0x05) || (cmd & 0x0f) == 0x0d) { - uptr->u3 |= LPR_POST; /* apply post CC */ + uptr->CMDu3 |= LPR_POST; /* apply post CC */ } sim_debug(DEBUG_CMD, &lpr_dev, "lpr_startcmd Cmd %02x\n", cmd); @@ -215,7 +221,6 @@ uint16 lpr_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) case 0x00: /* INCH command */ /* the IOP should already have the inch buffer set, so ignore */ sim_debug(DEBUG_CMD, &lpr_dev, "lpr_startcmd %04x: Cmd INCH\n", chan); -//fprintf(stderr, "lpr_startcmd %04x: Cmd INCH\n", chan); return SNS_CHNEND|SNS_DEVEND; /* all is well */ break; @@ -241,157 +246,162 @@ uint16 lpr_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) case 0x37: /* */ case 0x47: /* */ /* process the command */ - sim_debug(DEBUG_CMD, &lpr_dev, "lpr_startcmd %04x: Cmd %02x print\n", chan, cmd&LPR_CMDMSK); - uptr->u3 &= ~(LPR_CMDMSK); /* zero cmd */ - uptr->u3 |= (cmd & LPR_CMDMSK); /* save new command in u3 */ + sim_debug(DEBUG_CMD, &lpr_dev, + "lpr_startcmd %04x: Cmd %02x print\n", chan, cmd&LPR_CMDMSK); + uptr->CMDu3 &= ~(LPR_CMDMSK); /* zero cmd */ + uptr->CMDu3 |= (cmd & LPR_CMDMSK); /* save new command in CMDu3 */ sim_activate(uptr, 100); /* Start unit off */ - uptr->u5 = 0; /* no status */ - uptr->u6 = 0; /* start of buffer */ + uptr->SNSu5 = 0; /* no status */ + uptr->CBPu6 = 0; /* start of buffer */ return 0; /* we are good to go */ case 0x4: /* Sense Status */ - sim_debug(DEBUG_CMD, &lpr_dev, "lpr_startcmd %04x: Cmd %02x sense\n", chan, cmd&LPR_CMDMSK); - uptr->u3 &= ~(LPR_CMDMSK); /* zero cmd */ - uptr->u3 |= (cmd & LPR_CMDMSK); /* save new command in u3 */ + sim_debug(DEBUG_CMD, &lpr_dev, + "lpr_startcmd %04x: Cmd %02x sense\n", chan, cmd&LPR_CMDMSK); + uptr->CMDu3 &= ~(LPR_CMDMSK); /* zero cmd */ + uptr->CMDu3 |= (cmd & LPR_CMDMSK); /* save new command in CMDu3 */ sim_activate(uptr, 100); /* Start unit off */ - uptr->u5 = 0; /* no status */ - uptr->u6 = 0; /* start of buffer */ + uptr->SNSu5 = 0; /* no status */ + uptr->CBPu6 = 0; /* start of buffer */ return 0; /* we are good to go */ default: /* invalid command */ sim_debug(DEBUG_CMD, &lpr_dev, "lpr_startcmd %04x: Cmd %02x INVALID\n", chan, cmd&LPR_CMDMSK); - uptr->u5 |= SNS_CMDREJ; + uptr->SNSu5 |= SNS_CMDREJ; break; } - if (uptr->u5 & 0xff) -// return SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK; + if (uptr->SNSu5 & 0xff) return SNS_CHNEND|STATUS_PCHK; return SNS_CHNEND|SNS_DEVEND; } /* Handle transfer of data for printer */ t_stat lpr_srv(UNIT *uptr) { - int chsa = GET_UADDR(uptr->u3); - int u = (uptr - lpr_unit); - int cmd = (uptr->u3 & 0xff); + int chsa = GET_UADDR(uptr->CMDu3); + int u = (uptr - lpr_unit); + int cmd = (uptr->CMDu3 & 0xff); - sim_debug(DEBUG_CMD, &lpr_dev, "lpr_srv called chsa %04x cmd %02x u3 %08x cnt %04x\r\n", - chsa, cmd, uptr->u3, uptr->u6); + sim_debug(DEBUG_CMD, &lpr_dev, + "lpr_srv called chsa %04x cmd %02x CMDu3 %08x cnt %04x\r\n", + chsa, cmd, uptr->CMDu3, uptr->CBPu6); /* FIXME, need IOP lp status bit assignments */ if (cmd == 0x04) { /* sense? */ - uint8 ch = uptr->u5; /* get current status */ - uptr->u3 &= ~(LPR_CMDMSK); /* clear command */ + uint8 ch = uptr->SNSu5; /* get current status */ + uptr->CMDu3 &= ~(LPR_CMDMSK); /* clear command */ chan_write_byte(chsa, &ch); /* write the status to memory */ - uptr->u6 = 0; /* reset to beginning of buffer */ + uptr->CBPu6 = 0; /* reset to beginning of buffer */ chan_end(chsa, SNS_DEVEND|SNS_CHNEND); /* we are done */ return SCPE_OK; } /* process any CC before printing buffer */ - if ((uptr->u3 & LPR_PRE) && (((cmd & 0x03) == 0x03) || (cmd & 0x0f) == 0x0d)) { - uptr->u3 &= ~LPR_PRE; /* remove pre flag */ + if ((uptr->CMDu3 & LPR_PRE) && (((cmd & 0x03) == 0x03) || + (cmd & 0x0f) == 0x0d)) { + uptr->CMDu3 &= ~LPR_PRE; /* remove pre flag */ /* we have CC to do */ switch ((cmd & 0xf0) >> 4) { case 0: /* (0x0d) */ - lpr_data[u].lbuff[uptr->u6++] = 0x0d; + lpr_data[u].lbuff[uptr->CBPu6++] = 0x0d; break; case 3: /* */ - lpr_data[u].lbuff[uptr->u6++] = 0x0a; - uptr->u4++; /* increment the line count */ + lpr_data[u].lbuff[uptr->CBPu6++] = 0x0a; + uptr->CNTu4++; /* increment the line count */ /* drop thru */ case 2: /* */ - lpr_data[u].lbuff[uptr->u6++] = 0x0a; - uptr->u4++; /* increment the line count */ + lpr_data[u].lbuff[uptr->CBPu6++] = 0x0a; + uptr->CNTu4++; /* increment the line count */ /* drop thru */ case 1: /* (0x0a) */ - lpr_data[u].lbuff[uptr->u6++] = 0x0a; - uptr->u4++; /* increment the line count */ + lpr_data[u].lbuff[uptr->CBPu6++] = 0x0a; + uptr->CNTu4++; /* increment the line count */ break; case 4: /* (0x0c) */ - lpr_data[u].lbuff[uptr->u6++] = 0x0d; /* add C/R */ - lpr_data[u].lbuff[uptr->u6++] = 0x0a; /* add L/F */ - lpr_data[u].lbuff[uptr->u6++] = 0x0c; /* add FF */ - uptr->u4 = 0; /* restart line count */ + lpr_data[u].lbuff[uptr->CBPu6++] = 0x0d; /* add C/R */ + lpr_data[u].lbuff[uptr->CBPu6++] = 0x0a; /* add L/F */ + lpr_data[u].lbuff[uptr->CBPu6++] = 0x0c; /* add FF */ + uptr->CNTu4 = 0; /* restart line count */ break; } } /* Copy next byte from users buffer */ - while ((uptr->u3 & LPR_FULL) == 0) { /* copy in a char if not full */ - if(chan_read_byte(chsa, &lpr_data[u].lbuff[uptr->u6])) { - uptr->u3 |= LPR_FULL; /* end of buffer or error */ + while ((uptr->CMDu3 & LPR_FULL) == 0) { /* copy in a char if not full */ + if(chan_read_byte(chsa, &lpr_data[u].lbuff[uptr->CBPu6])) { + uptr->CMDu3 |= LPR_FULL; /* end of buffer or error */ break; /* done reading */ } else { /* remove nulls */ - if (lpr_data[u].lbuff[uptr->u6] == '\0') { - lpr_data[u].lbuff[uptr->u6] = ' '; + if (lpr_data[u].lbuff[uptr->CBPu6] == '\0') { + lpr_data[u].lbuff[uptr->CBPu6] = ' '; } /* remove backspace */ - if (lpr_data[u].lbuff[uptr->u6] == 0x8) { - lpr_data[u].lbuff[uptr->u6] = ' '; + if (lpr_data[u].lbuff[uptr->CBPu6] == 0x8) { + lpr_data[u].lbuff[uptr->CBPu6] = ' '; } - uptr->u6++; /* next buffer loc */ + uptr->CBPu6++; /* next buffer loc */ } } /* remove trailing blanks before we apply trailing carriage control */ - while (uptr->u6 > 0) { - if ((lpr_data[u].lbuff[uptr->u6-1] == ' ') || - (lpr_data[u].lbuff[uptr->u6-1] == '\0')) { - uptr->u6--; + while (uptr->CBPu6 > 0) { + if ((lpr_data[u].lbuff[uptr->CBPu6-1] == ' ') || + (lpr_data[u].lbuff[uptr->CBPu6-1] == '\0')) { + uptr->CBPu6--; continue; } break; } /* process any CC after printing buffer */ - if ((uptr->u3 & LPR_FULL) && (uptr->u3 & LPR_POST) && ((cmd & 0x0f) == 0x0d)) { + if ((uptr->CMDu3 & LPR_FULL) && (uptr->CMDu3 & LPR_POST) && + ((cmd & 0x0f) == 0x0d)) { /* we have CC to do */ - uptr->u3 &= ~LPR_POST; /* remove post flag */ - lpr_data[u].lbuff[uptr->u6++] = 0x0d; /* just a */ + uptr->CMDu3 &= ~LPR_POST; /* remove post flag */ + lpr_data[u].lbuff[uptr->CBPu6++] = 0x0d; /* just a */ } /* process any CC after printing buffer */ - if ((uptr->u3 & LPR_FULL) && (uptr->u3 & LPR_POST) && ((cmd & 0x0f) == 0x05)) { + if ((uptr->CMDu3 & LPR_FULL) && (uptr->CMDu3 & LPR_POST) && + ((cmd & 0x0f) == 0x05)) { /* we have CC to do */ - uptr->u3 &= ~LPR_POST; /* remove post flag */ + uptr->CMDu3 &= ~LPR_POST; /* remove post flag */ switch ((cmd & 0xf0) >> 4) { case 0: /* (0x0d) */ - lpr_data[u].lbuff[uptr->u6++] = 0x0d; + lpr_data[u].lbuff[uptr->CBPu6++] = 0x0d; break; case 3: /* */ - lpr_data[u].lbuff[uptr->u6++] = 0x0a; - uptr->u4++; /* increment the line count */ + lpr_data[u].lbuff[uptr->CBPu6++] = 0x0a; + uptr->CNTu4++; /* increment the line count */ /* drop thru */ case 2: /* */ - lpr_data[u].lbuff[uptr->u6++] = 0x0a; - uptr->u4++; /* increment the line count */ + lpr_data[u].lbuff[uptr->CBPu6++] = 0x0a; + uptr->CNTu4++; /* increment the line count */ /* drop thru */ case 1: /* (0x0a) */ - lpr_data[u].lbuff[uptr->u6++] = 0x0a; - uptr->u4++; /* increment the line count */ + lpr_data[u].lbuff[uptr->CBPu6++] = 0x0a; + uptr->CNTu4++; /* increment the line count */ break; case 4: /* (0x0c) */ - lpr_data[u].lbuff[uptr->u6++] = 0x0d; /* add C/R */ - lpr_data[u].lbuff[uptr->u6++] = 0x0a; /* add L/F */ - lpr_data[u].lbuff[uptr->u6++] = 0x0c; /* add FF */ - uptr->u4 = 0; /* restart line count */ + lpr_data[u].lbuff[uptr->CBPu6++] = 0x0d; /* add C/R */ + lpr_data[u].lbuff[uptr->CBPu6++] = 0x0a; /* add L/F */ + lpr_data[u].lbuff[uptr->CBPu6++] = 0x0c; /* add FF */ + uptr->CNTu4 = 0; /* restart line count */ break; } } /* print the line if buffer is full */ - if (uptr->u3 & LPR_FULL || uptr->u6 >= 156) { - lpr_data[u].lbuff[uptr->u6] = 0x00; /* NULL terminate */ - sim_fwrite(&lpr_data[u].lbuff, 1, uptr->u6, uptr->fileref); /* Print our buffer */ + if (uptr->CMDu3 & LPR_FULL || uptr->CBPu6 >= 156) { + lpr_data[u].lbuff[uptr->CBPu6] = 0x00; /* NULL terminate */ + sim_fwrite(&lpr_data[u].lbuff, 1, uptr->CBPu6, uptr->fileref); /* Print our buffer */ sim_debug(DEBUG_DETAIL, &lpr_dev, "LPR %s", (char*)&lpr_data[u].lbuff); - uptr->u3 &= ~(LPR_FULL|LPR_CMDMSK); /* clear old status */ - uptr->u6 = 0; /* start at beginning of buffer */ - uptr->u4++; /* increment the line count */ - if ((uint32)uptr->u4 > uptr->capac) { /* see if at max lines/page */ - uptr->u4 = 0; /* yes, restart count */ + uptr->CMDu3 &= ~(LPR_FULL|LPR_CMDMSK); /* clear old status */ + uptr->CBPu6 = 0; /* start at beginning of buffer */ + uptr->CNTu4++; /* increment the line count */ + if ((uint32)uptr->CNTu4 > uptr->capac) { /* see if at max lines/page */ + uptr->CNTu4 = 0; /* yes, restart count */ chan_end(chsa, SNS_DEVEND|SNS_CHNEND|SNS_UNITEXP); /* we are done */ } else chan_end(chsa, SNS_DEVEND|SNS_CHNEND); /* we are done */ @@ -420,7 +430,7 @@ t_stat lpr_setlpp(UNIT *uptr, int32 val, CONST char *cptr, void *desc) if (i < 20 || i > 100) return SCPE_ARG; uptr->capac = i; - uptr->u4 = 0; + uptr->CNTu4 = 0; return SCPE_OK; } @@ -434,15 +444,32 @@ t_stat lpr_getlpp(FILE *st, UNIT *uptr, int32 v, CONST void *desc) } /* attach a file to the line printer device */ -t_stat lpr_attach(UNIT * uptr, CONST char *file) +t_stat lpr_attach(UNIT *uptr, CONST char *file) { - t_stat r; + t_stat r; + uint16 chsa = GET_UADDR(uptr->CMDu3); /* get address of lpr device */ + DEVICE *dptr = get_dev(uptr); /* get device pointer */ + DIB *dibp = 0; if ((r = attach_unit(uptr, file)) != SCPE_OK) return r; - uptr->u3 &= ~(LPR_FULL|LPR_CMDMSK); - uptr->u4 = 0; - uptr->u5 = 0; + uptr->CMDu3 &= ~(LPR_FULL|LPR_CMDMSK); + uptr->CNTu4 = 0; + uptr->SNSu5 = 0; + + /* check for valid configured lpr */ + /* must have valid DIB and Channel Program pointer */ + dibp = (DIB *)dptr->ctxt; /* get the DIB pointer */ + if ((dib_unit[chsa] == NULL) || (dibp == NULL) || (dibp->chan_prg == NULL)) { + sim_debug(DEBUG_CMD, dptr, + "ERROR===ERROR\nLPR device %s not configured on system, aborting\n", + dptr->name); + printf("ERROR===ERROR\nLPR device %s not configured on system, aborting\n", + dptr->name); + detach_unit(uptr); /* detach if error */ + return SCPE_UNATT; /* error */ + } + set_devattn(chsa, SNS_DEVEND); /* ready int???? */ return SCPE_OK; } diff --git a/SEL32/sel32_mfp.c b/SEL32/sel32_mfp.c index 7d3e247..48ac8b7 100644 --- a/SEL32/sel32_mfp.c +++ b/SEL32/sel32_mfp.c @@ -1,4 +1,4 @@ -/* sel32_mfp.c: SEL-32 Model 8000/8001/8002 MFP processor controller +/* sel32_mfp.c: SEL-32 Model 8002 MFP processor controller Copyright (c) 2018-2020, James C. Bevier @@ -125,8 +125,6 @@ DEVICE mfp_dev = { NULL, NULL, NULL, /* boot, attach, detach */ /* dib ptr, dev flags, debug flags, debug */ &mfp_dib, DEV_CHAN|DEV_DIS|DEV_DISABLE|DEV_DEBUG, 0, dev_debug, -// NULL, NULL, &mfp_help, /* ?, ?, help */ -// NULL, NULL, &mfp_desc /* ?, ?, description */ }; /* MFP controller routines */ @@ -165,10 +163,8 @@ uint16 mfp_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) mfp_chp[0].chan_inch_addr); /* set inch buffer addr */ mfp_chp[0].chan_inch_addr = mfp_chp[0].ccw_addr; /* set inch buffer addr */ -// set_inch(uptr, mfp_chp[0].ccw_addr); /* new address */ uptr->u3 |= MFP_INCH2; /* save INCH command as 0xf0 */ -//@ sim_activate(uptr, 20); /* go on */ sim_activate(uptr, 40); /* go on */ return 0; /* no status change */ break; @@ -178,8 +174,7 @@ uint16 mfp_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) uptr->u5 = SNS_RDY|SNS_ONLN; /* status is online & ready */ uptr->u3 &= LMASK; /* leave only chsa */ uptr->u3 |= (cmd & MFP_MSK); /* save NOP command */ - sim_activate(uptr, 20); /* TRY 07-13-19 */ -//@41 sim_activate(uptr, 40); /* TRY 07-13-19 */ + sim_activate(uptr, 40); /* TRY 07-13-19 */ return 0; /* no status change */ break; @@ -188,8 +183,7 @@ uint16 mfp_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) uptr->u5 = SNS_RDY|SNS_ONLN; /* status is online & ready */ uptr->u3 &= LMASK; /* leave only chsa */ uptr->u3 |= (cmd & MFP_MSK); /* save SID command */ - sim_activate(uptr, 20); /* TRY 07-13-19 */ -//@41 sim_activate(uptr, 40); /* TRY 07-13-19 */ + sim_activate(uptr, 40); /* TRY 07-13-19 */ return 0; /* no status change */ break; @@ -199,8 +193,7 @@ uint16 mfp_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) chan, cmd, uptr->u5); uptr->u3 &= LMASK; /* leave only chsa */ uptr->u3 |= (cmd & MFP_MSK); /* save command */ - sim_activate(uptr, 20); /* force interrupt */ -//@41 sim_activate(uptr, 40); /* force interrupt */ + sim_activate(uptr, 40); /* force interrupt */ return 0; /* no status change */ break; } @@ -214,8 +207,6 @@ t_stat mfp_srv(UNIT *uptr) uint16 chsa = GET_UADDR(uptr->u3); int cmd = uptr->u3 & MFP_MSK; CHANP *chp = &mfp_chp[0]; /* find the chanp pointer */ -// int i; -// int len = chp->ccw_count; /* INCH command count */ uint32 mema = chp->ccw_addr; /* get inch or buffer addr */ /* test for NOP or INCH cmds */ @@ -282,12 +273,9 @@ t_stat mfp_srv(UNIT *uptr) /* the chp->ccw_addr location contains the inch address */ /* call set_inch() to setup inch buffer */ //FIXME add code to test return -// i = set_inch(uptr, mema); /* new address */ set_inch(uptr, mema); /* new address */ -// chp->chan_inch_addr = mema; /* set inch buffer addr */ uptr->u3 &= LMASK; /* clear the cmd */ chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* we are done dev|chan end */ -// chan_end(chsa, SNS_CHNEND); /* we are done dev|chan end */ } return SCPE_OK; } @@ -305,8 +293,6 @@ t_stat mfp_help(FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, CONST char *cptr fprintf(st, "The MFP fields all interrupts and status posting\r\n"); fprintf(st, "for each of the controllers on the system.\r\n"); fprintf(st, "Nothing can be configured for this Channel.\r\n"); -// fprint_set_help(st, dptr); -// fprint_show_help(st, dptr); return SCPE_OK; } diff --git a/SEL32/sel32_mt.c b/SEL32/sel32_mt.c index c5d0b00..423abde 100644 --- a/SEL32/sel32_mt.c +++ b/SEL32/sel32_mt.c @@ -165,7 +165,7 @@ uint8 mt_busy[NUM_DEVS_MT]; /* Gould Buffered Tape Processor (BTP) - Model 8051 */ /* Integrated channel controller */ -/* Class F MT BTP I/O device status responce in IOCD address pointer location */ +/* Class F MT BTP I/O device status response in IOCD address pointer location */ /* |-------+-------+-------+-------+-------+-------+-------+-------| */ /* |0 0 0 0|0 0 0 0|0 0 1 1|1 1 1 1|1 1 1 1|2 2 2 2|2 2 2 2|2 2 3 3| */ /* |0 1 2 3|4 5 6 7|8 9 0 1|2 3 4 5|6 7 8 9|0 1 2 3|4 5 6 7|8 9 3 1| */ @@ -355,7 +355,6 @@ DEVICE mtb_dev = { "MTB", mtb_unit, NULL, mt_mod, NUM_UNITS_MT, 8, 15, 1, 8, 8, NULL, NULL, &mt_reset, &mt_boot, &mt_attach, &mt_detach, -// &mtb_dib, DEV_BUF_NUM(1)|DEV_DIS|DEV_DISABLE|DEV_DEBUG|DEV_TAPE, 0, dev_debug &mtb_dib, DEV_BUF_NUM(1)|DEV_DISABLE|DEV_DEBUG|DEV_TAPE, 0, dev_debug NULL, NULL, &mt_help, NULL, NULL, &mt_description }; @@ -368,11 +367,6 @@ uint16 mt_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) DEVICE *dptr = get_dev(uptr); int unit = (uptr - dptr->units); CHANP *chp = find_chanp_ptr(chsa); /* find the chanp pointer */ -#ifdef DO_NO_INT - int i; - uint8 ch; - uint16 len; -#endif sim_debug(DEBUG_EXP, &mta_dev, "mt_startcmd entry chan %04x cmd %02x\n", chan, cmd); if (mt_busy[GET_DEV_BUF(dptr->flags)] != 0 || (uptr->CMD & MT_CMDMSK) != 0) { @@ -387,10 +381,6 @@ uint16 mt_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) case 0x00: /* INCH command */ sim_debug(DEBUG_CMD, dptr, "start INCH command\n"); -#ifdef DO_DYNAMIC_DEBUG - /* start debugging */ - cpu_dev.dctrl |= (DEBUG_INST | DEBUG_CMD | DEBUG_EXP | DEBUG_IRQ | DEBUG_TRAP); -#endif sim_debug(DEBUG_CMD, dptr, "mt_startcmd starting INCH cmd, chsa %04x MemBuf %08x cnt %04x\n", chsa, chp->ccw_addr, chp->ccw_count); @@ -434,16 +424,7 @@ uint16 mt_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) uptr->SNS |= (SNS_EOT); /* tape at EOM */ /* Fall through */ -#ifndef DO_NO_INT case 0x04: /* Sense */ -#endif -// case 0x80: /* Unknown diag cmd with byte cnt of 0x0c */ -#ifdef DO_DYNAMIC_DEBUG - if ((cmd & 0xff) == 0x80) { - /* start debugging */ - cpu_dev.dctrl |= (DEBUG_INST | DEBUG_CMD | DEBUG_EXP | DEBUG_IRQ | DEBUG_TRAP); - } -#endif uptr->CMD &= ~(MT_CMDMSK); /* clear out last cmd */ uptr->CMD |= cmd & MT_CMDMSK; /* insert new cmd */ CLR_BUF(uptr); /* buffer is empty */ @@ -452,49 +433,24 @@ uint16 mt_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) sim_debug(DEBUG_EXP, &mta_dev, "mt_startcmd sense %08x return 0 chan %04x cmd %02x\n", uptr->SNS, chan, cmd); sim_activate(uptr, 100); /* Start unit off */ -//@41 sim_activate(uptr, 150); /* Start unit off */ return 0; -#ifdef DO_NO_INT - case 0x04: /* Sense */ - /* write requested status */ - len = chp->ccw_count; /* command count */ - for (i=0; iSNS >> (24-(i*8))) & 0xff; /* get 8 bits of status */ - chan_write_byte(chsa, &ch); /* write zero byte */ - sim_debug(DEBUG_CMD, &mta_dev, - "sense unit %02x byte %1x %02x\n", unit, i, ch); - } - uptr->CMD &= ~MT_CMDMSK; /* clear the cmd */ - sim_debug(DEBUG_CMD, &mta_dev, "mt_srv SENSE %08x char complete unit=%02x\n", - uptr->SNS, unit); - return SNS_CHNEND|SNS_DEVEND; - break; -#endif - default: /* invalid command */ sim_debug(DEBUG_EXP, &mta_dev, "mt_startcmd CMDREJ return chan %04x cmd %02x\n", chan, cmd); uptr->SNS |= SNS_CMDREJ; -#ifdef DO_DYNAMIC_DEBUG - if ((cmd & 0xff) == 0x80) { - /* start debugging */ - cpu_dev.dctrl |= (DEBUG_INST | DEBUG_CMD | DEBUG_EXP | DEBUG_IRQ | DEBUG_TRAP); - } -#endif /* send program check */ -// return SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK|STATUS_PCHK; -// return SNS_CHNEND|SNS_DEVEND|STATUS_PCHK; return SNS_CHNEND|STATUS_PCHK; break; } +#if 0 + /* not reached */ if (uptr->SNS & 0xff000000) /* errors? */ return SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK; sim_debug(DEBUG_EXP, &mta_dev, "mt_startcmd ret CHNEND|DEVEND chan %04x unit %04x cmd %02x\n", chan, unit, cmd); return SNS_CHNEND|SNS_DEVEND; +#endif } /* Map simH errors into machine errors */ @@ -505,7 +461,7 @@ t_stat mt_error(UNIT *uptr, uint16 addr, t_stat r, DEVICE *dptr) switch (r) { /* switch on return value */ case MTSE_OK: /* no error */ -/*NEW*/ chan_end(addr, SNS_CHNEND|SNS_DEVEND); /* we are done with command */ + chan_end(addr, SNS_CHNEND|SNS_DEVEND); /* we are done with command */ break; case MTSE_TMK: /* tape mark */ @@ -517,7 +473,7 @@ t_stat mt_error(UNIT *uptr, uint16 addr, t_stat r, DEVICE *dptr) case MTSE_WRP: /* write protected */ uptr->SNS |= SNS_WRP; /* write protected */ sim_debug(DEBUG_CMD, &mta_dev, "WRITE PROTECT %08x\n", r); /* operator intervention */ -/*NEW*/ chan_end(addr, SNS_CHNEND|SNS_DEVEND); /* we are done with command */ + chan_end(addr, SNS_CHNEND|SNS_DEVEND); /* we are done with command */ break; case MTSE_UNATT: /* unattached */ @@ -530,13 +486,13 @@ t_stat mt_error(UNIT *uptr, uint16 addr, t_stat r, DEVICE *dptr) case MTSE_FMT: /* invalid format */ case MTSE_RECE: /* error in record */ sim_debug(DEBUG_CMD, &mta_dev, "ERROR %08x\n", r); -/*NEW*/ chan_end(addr, SNS_CHNEND|SNS_DEVEND); /* we are done with command */ + chan_end(addr, SNS_CHNEND|SNS_DEVEND); /* we are done with command */ break; case MTSE_BOT: /* beginning of tape */ uptr->SNS |= SNS_LOAD; /* tape at BOT */ sim_debug(DEBUG_CMD, &mta_dev, "BOT\n"); -/*NEW*/ chan_end(addr, SNS_CHNEND|SNS_DEVEND); /* we are done with command */ + chan_end(addr, SNS_CHNEND|SNS_DEVEND); /* we are done with command */ break; case MTSE_INVRL: /* invalid rec lnt */ @@ -546,7 +502,6 @@ t_stat mt_error(UNIT *uptr, uint16 addr, t_stat r, DEVICE *dptr) chan_end(addr, SNS_CHNEND|SNS_DEVEND|SNS_UNITEXP); break; } -//WAS chan_end(addr, SNS_CHNEND|SNS_DEVEND); /* we are done with command */ return SCPE_OK; } @@ -584,10 +539,6 @@ t_stat mt_srv(UNIT *uptr) sim_debug(DEBUG_CMD, dptr, "mt_srv starting INCH %06x cmd, chsa %04x MemBuf %06x cnt %04x\n", mema, addr, chp->ccw_addr, chp->ccw_count); -#ifdef DO_DYNAMIC_DEBUG - /* start debugging */ - cpu_dev.dctrl |= (DEBUG_INST | DEBUG_CMD | DEBUG_EXP | DEBUG_IRQ | DEBUG_TRAP); -#endif if (len == 0) { /* we have invalid count, error, bail out */ @@ -606,27 +557,10 @@ t_stat mt_srv(UNIT *uptr) } /* just dump data */ } -#ifdef CHANGE_FOR_UTX_BTP_TEST - /* a BTP uses a 41 word INCH memory buffer */ -// for (i=0; i<41; i++) { - for (i=0; i<9; i++) { - int32 data = RMW(mema+(4*i)); /* get data word */ - sim_debug(DEBUG_CMD, dptr, - "mt_srv INCH buffer addr %06x, wd %02x data %08x\n", - mema+(4*i), 4*i, data); - /* zero the data */ - if (i == 8) - WMW(mema+(4*i),0x00050005); /* show we are a BTP */ - else - WMW(mema+(4*i),0); /* zero work location */ - } -#endif /* the chp->ccw_addr location contains the inch address */ /* call set_inch() to setup inch buffer */ i = set_inch(uptr, mema); /* new address */ - //FIXME - add back code? -#ifndef NOTYET if ((i == SCPE_MEM) || (i == SCPE_ARG)) { /* any error */ /* we have error, bail out */ uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ @@ -634,7 +568,6 @@ t_stat mt_srv(UNIT *uptr) chan_end(addr, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); break; } -#endif /* set halfwords 16 & 17 to 5 as default retry count in inch data */ /* UTX uses this value to see if the device is a buffered tape processor */ /* they must be non-zero and equal to be BTP */ @@ -648,7 +581,6 @@ t_stat mt_srv(UNIT *uptr) chan_end(addr, SNS_CHNEND|SNS_DEVEND); /* we are done dev|chan end */ break; -#ifndef FIX_DIAG case 0x80: /* other? */ /* default to NOP */ sim_debug(DEBUG_CMD, &mta_dev, "mt_srv cmd 80 DIAG unit=%04x SNS %08x\n", unit, uptr->SNS); ch = (uptr->SNS >> 24) & 0xff; /* get sense byte 0 status */ @@ -663,7 +595,6 @@ t_stat mt_srv(UNIT *uptr) ch = (uptr->SNS >> 0) & 0xff; /* get sense byte 3 status */ sim_debug(DEBUG_CMD, &mta_dev, "sense unit %02x byte 3 %02x\n", unit, ch); chan_write_byte(addr, &ch); /* write byte 3 */ -#ifndef NO_HARDWARE_STATUS_FOR_DIAGS /* write zero extra status */ for (ch=4; ch < 0xc; ch++) { uint8 zc = 0; @@ -671,33 +602,6 @@ t_stat mt_srv(UNIT *uptr) sim_debug(DEBUG_CMD, &mta_dev, "sense unit %02x byte %1x %02x\n", unit, ch, zc); } -#else /* FOR UTX */ - /* write status 2 more times */ - ch = (uptr->SNS >> 24) & 0xff; /* get sense byte 0 status */ - sim_debug(DEBUG_CMD, &mta_dev, "sense unit %02x byte 0 %02x\n", unit, ch); - chan_write_byte(addr, &ch); /* write byte 0 */ - ch = (uptr->SNS >> 16) & 0xff; /* get sense byte 1 status */ - sim_debug(DEBUG_CMD, &mta_dev, "sense unit %02x byte 1 %02x\n", unit, ch); - chan_write_byte(addr, &ch); /* write byte 1 */ - ch = (uptr->SNS >> 8) & 0xff; /* get sense byte 2 status */ - sim_debug(DEBUG_CMD, &mta_dev, "sense unit %02x byte 2 %02x\n", unit, ch); - chan_write_byte(addr, &ch); /* write byte 2 */ - ch = (uptr->SNS >> 0) & 0xff; /* get sense byte 3 status */ - sim_debug(DEBUG_CMD, &mta_dev, "sense unit %02x byte 3 %02x\n", unit, ch); - chan_write_byte(addr, &ch); /* write byte 3 */ - ch = (uptr->SNS >> 24) & 0xff; /* get sense byte 0 status */ - sim_debug(DEBUG_CMD, &mta_dev, "sense unit %02x byte 0 %02x\n", unit, ch); - chan_write_byte(addr, &ch); /* write byte 0 */ - ch = (uptr->SNS >> 16) & 0xff; /* get sense byte 1 status */ - sim_debug(DEBUG_CMD, &mta_dev, "sense unit %02x byte 1 %02x\n", unit, ch); - chan_write_byte(addr, &ch); /* write byte 1 */ - ch = (uptr->SNS >> 8) & 0xff; /* get sense byte 2 status */ - sim_debug(DEBUG_CMD, &mta_dev, "sense unit %02x byte 2 %02x\n", unit, ch); - chan_write_byte(addr, &ch); /* write byte 2 */ - ch = (uptr->SNS >> 0) & 0xff; /* get sense byte 3 status */ - sim_debug(DEBUG_CMD, &mta_dev, "sense unit %02x byte 3 %02x\n", unit, ch); - chan_write_byte(addr, &ch); /* write byte 3 */ -#endif uptr->CMD &= ~MT_CMDMSK; /* clear the cmd */ mt_busy[bufnum] &= ~1; /* make our buffer not busy */ sim_debug(DEBUG_CMD, &mta_dev, "mt_srv DIAG SNS %08x char complete unit=%02x\n", @@ -705,7 +609,6 @@ t_stat mt_srv(UNIT *uptr) chan_end(addr, SNS_CHNEND|SNS_DEVEND); /* we are done dev|chan end */ break; -#endif case MT_NOP: /* 0x03 */ /* NOP motion command */ uptr->CMD &= ~MT_CMDMSK; /* clear the cmd */ mt_busy[bufnum] &= ~1; /* make our buffer not busy */ @@ -773,7 +676,6 @@ t_stat mt_srv(UNIT *uptr) /* Send dummy character to force SLI */ chan_write_byte(addr, &ch); /* write the byte */ sim_debug(DEBUG_CMD, &mta_dev, "Read unit %02x send dump SLI\n", unit); -//@41 sim_activate(uptr, (uptr->hwmark-uptr->POS) * 10); /* wait again */ sim_activate(uptr, (uptr->hwmark-uptr->POS) * 10); /* wait again */ uptr->CMD |= MT_READDONE; /* read is done */ break; @@ -793,19 +695,10 @@ t_stat mt_srv(UNIT *uptr) sim_debug(DEBUG_CMD, &mta_dev, "Read too much data unit %02x cnt %04x ch %02x hwm %04x\n", unit, uptr->POS, ch, uptr->hwmark); -#ifdef UTX_EOF_CHANGE - uptr->CMD &= ~MT_CMDMSK; /* clear the cmd */ - mt_busy[bufnum] &= ~1; /* set not busy */ - chan_end(addr, SNS_CHNEND|SNS_DEVEND); /* return end status */ -#else -// uptr->SNS |= SNS_OVRRUN; /* data overrun */ uptr->CMD |= MT_READDONE; /* read is done */ - sim_activate(uptr, 20); /* wait again */ -//@41 sim_activate(uptr, 40); /* wait again */ -#endif + sim_activate(uptr, 40); /* wait again */ } else - sim_activate(uptr, 20); /* wait again */ -//@41 sim_activate(uptr, 40); /* wait again */ + sim_activate(uptr, 40); /* wait again */ } break; @@ -830,8 +723,7 @@ t_stat mt_srv(UNIT *uptr) sim_debug(DEBUG_CMD, &mta_dev, "Write mode data in unit %02x POS %04x ch %02x\n", unit, uptr->POS, ch); uptr->hwmark = uptr->POS; /* set high water mark */ - sim_activate(uptr, 20); /* wait time */ -//@41 sim_activate(uptr, 40); /* wait again */ + sim_activate(uptr, 40); /* wait time */ } break; @@ -863,8 +755,7 @@ t_stat mt_srv(UNIT *uptr) unit, uptr->POS, ch); uptr->hwmark = uptr->POS; } - sim_activate(uptr, 20); -//@41 sim_activate(uptr, 40); + sim_activate(uptr, 40); break; case MT_RDBK: /* 0x0C */ /* Read Backwards */ @@ -900,7 +791,6 @@ t_stat mt_srv(UNIT *uptr) unit, uptr->POS); /* If not read whole record, skip till end */ if (uptr->POS >= 0) { -//@41 sim_activate(uptr, (uptr->POS) * 20); sim_activate(uptr, (uptr->POS) * 20); uptr->CMD |= MT_READDONE; return SCPE_OK; @@ -916,8 +806,7 @@ t_stat mt_srv(UNIT *uptr) mt_busy[bufnum] &= ~1; chan_end(addr, SNS_CHNEND|SNS_DEVEND); } else - sim_activate(uptr, 20); -//@41 sim_activate(uptr, 40); + sim_activate(uptr, 40); } break; @@ -936,7 +825,7 @@ t_stat mt_srv(UNIT *uptr) sim_debug(DEBUG_CMD, &mta_dev, "Write Mark unit=%02x\n", unit); uptr->CMD &= ~(MT_CMDMSK); r = sim_tape_wrtmk(uptr); - chan_end(addr, SNS_DEVEND); //NEW chan_end(addr, SNS_CHNEND|SNS_DEVEND); + chan_end(addr, SNS_DEVEND); mt_busy[bufnum] &= ~1; } break; @@ -954,7 +843,6 @@ t_stat mt_srv(UNIT *uptr) } uptr->POS++; sim_activate(uptr, 50); -//@41 sim_activate(uptr, 80); break; case 1: uptr->POS++; @@ -966,11 +854,9 @@ t_stat mt_srv(UNIT *uptr) uptr->POS++; sim_debug(DEBUG_CMD, &mta_dev, "MARK\n"); sim_activate(uptr, 50); -//@41 sim_activate(uptr, 80); } else { sim_debug(DEBUG_CMD, &mta_dev, "Backspace reclen %04x\n", reclen); sim_activate(uptr, 50); -//@41 sim_activate(uptr, 80); } break; case 2: @@ -1006,25 +892,22 @@ t_stat mt_srv(UNIT *uptr) uptr->POS++; sim_debug(DEBUG_DETAIL, &mta_dev, "MARK\n"); sim_activate(uptr, 50); -//@41 sim_activate(uptr, 80); } else if (r == MTSE_BOT) { uptr->POS+= 2; sim_activate(uptr, 50); -//@41 sim_activate(uptr, 80); } else { sim_activate(uptr, 20); -//@41 sim_activate(uptr, 80); } break; case 2: /* File Mark */ uptr->CMD &= ~(MT_CMDMSK); mt_busy[bufnum] &= ~1; - chan_end(addr, SNS_DEVEND); //NEW chan_end(addr, SNS_CHNEND|SNS_DEVEND); + chan_end(addr, SNS_DEVEND); break; case 3: /* BOT */ uptr->CMD &= ~(MT_CMDMSK); mt_busy[bufnum] &= ~1; - chan_end(addr, SNS_DEVEND); //NEW chan_end(addr, SNS_CHNEND|SNS_DEVEND); + chan_end(addr, SNS_DEVEND); break; } break; @@ -1035,7 +918,6 @@ t_stat mt_srv(UNIT *uptr) sim_debug(DEBUG_CMD, &mta_dev, "Skip rec entry unit=%02x ", unit); uptr->POS++; sim_activate(uptr, 50); -//@41 sim_activate(uptr, 80); break; case 1: uptr->POS++; @@ -1046,36 +928,32 @@ t_stat mt_srv(UNIT *uptr) uptr->SNS |= SNS_FMRKDT; /* file mark detected */ sim_debug(DEBUG_CMD, &mta_dev, "FSR MARK\n"); sim_activate(uptr, 50); -//@41 sim_activate(uptr, 80); } else if (r == MTSE_EOM) { uptr->POS = 4; uptr->SNS |= SNS_EOT; /* set EOT status */ sim_activate(uptr, 50); -//@41 sim_activate(uptr, 80); } else { sim_debug(DEBUG_CMD, &mta_dev, "FSR skipped %04x byte record\n", reclen); sim_activate(uptr, 10 + (10 * reclen)); -//@41 sim_activate(uptr, 10 + (10 * reclen)); } break; case 2: uptr->CMD &= ~(MT_CMDMSK); mt_busy[bufnum] &= ~1; sim_debug(DEBUG_CMD, &mta_dev, "Skip record Completed\n"); - chan_end(addr, SNS_DEVEND); //NEW chan_end(addr, SNS_CHNEND|SNS_DEVEND); + chan_end(addr, SNS_DEVEND); break; case 3: uptr->CMD &= ~(MT_CMDMSK); mt_busy[bufnum] &= ~1; sim_debug(DEBUG_CMD, &mta_dev, "Skip record at EOF\n"); - chan_end(addr, SNS_DEVEND|SNS_UNITEXP); //NEW chan_end(addr, SNS_CHNEND|SNS_DEVEND|SNS_UNITEXP); + chan_end(addr, SNS_DEVEND|SNS_UNITEXP); break; case 4: uptr->CMD &= ~(MT_CMDMSK); mt_busy[bufnum] &= ~1; sim_debug(DEBUG_CMD, &mta_dev, "Skip record at EOT\n"); -//BAD chan_end(addr, SNS_DEVEND|SNS_UNITCHK); chan_end(addr, SNS_DEVEND|SNS_UNITEXP); break; } @@ -1084,10 +962,10 @@ t_stat mt_srv(UNIT *uptr) case MT_FSF: /* 0x63 */ /* advance filemark */ switch(uptr->POS) { case 0: - sim_debug(DEBUG_CMD, &mta_dev, "Skip file entry sense %08x unit %02x\n", uptr->SNS, unit); + sim_debug(DEBUG_CMD, &mta_dev, + "Skip file entry sense %08x unit %02x\n", uptr->SNS, unit); uptr->POS++; sim_activate(uptr, 50); -//@41 sim_activate(uptr, 80); break; case 1: sim_debug(DEBUG_CMD, &mta_dev, "Skip file unit=%02x\n", unit); @@ -1097,24 +975,22 @@ t_stat mt_srv(UNIT *uptr) uptr->SNS |= SNS_FMRKDT; /* file mark detected */ sim_debug(DEBUG_CMD, &mta_dev, "FSF EOF MARK sense %08x\n", uptr->SNS); sim_activate(uptr, 50); -//@41 sim_activate(uptr, 80); } else if (r == MTSE_EOM) { uptr->SNS |= SNS_EOT; /* set EOT status */ sim_debug(DEBUG_CMD, &mta_dev, "FSF EOT sense %08x\n", uptr->SNS); uptr->POS+= 2; sim_activate(uptr, 50); -//@41 sim_activate(uptr, 80); } else { sim_debug(DEBUG_CMD, &mta_dev, "FSF skipped %04x byte record\n", reclen); sim_activate(uptr, 50); -//@41 sim_activate(uptr, 80); } break; case 2: uptr->CMD &= ~(MT_CMDMSK); mt_busy[bufnum] &= ~1; uptr->SNS &= ~SNS_LOAD; /* reset BOT */ - sim_debug(DEBUG_CMD, &mta_dev, "Skip file done sense %08x unit %02x\n", uptr->SNS, unit); + sim_debug(DEBUG_CMD, &mta_dev, + "Skip file done sense %08x unit %02x\n", uptr->SNS, unit); chan_end(addr, SNS_CHNEND|SNS_DEVEND); /* we are done dev|chan end */ break; case 3: @@ -1122,9 +998,8 @@ t_stat mt_srv(UNIT *uptr) uptr->SNS &= ~SNS_LOAD; /* reset BOT */ uptr->SNS |= SNS_EOT; /* set EOT status */ mt_busy[bufnum] &= ~1; - sim_debug(DEBUG_CMD, &mta_dev, "Skip file got EOT sense %08x unit %02x\n", uptr->SNS, unit); -//BAD chan_end(addr, SNS_DEVEND|SNS_UNITCHK); -//*##*/ chan_end(addr, SNS_DEVEND|SNS_UNITCHK); + sim_debug(DEBUG_CMD, &mta_dev, + "Skip file got EOT sense %08x unit %02x\n", uptr->SNS, unit); chan_end(addr, SNS_DEVEND|SNS_UNITEXP); break; } @@ -1137,12 +1012,10 @@ t_stat mt_srv(UNIT *uptr) uptr->SNS |= SNS_CMDREJ; uptr->CMD &= ~MT_CMDMSK; mt_busy[bufnum] &= ~1; -//BAD chan_end(addr, SNS_DEVEND|SNS_UNITCHK); chan_end(addr, SNS_DEVEND|SNS_UNITEXP); } else { uptr->POS ++; sim_activate(uptr, 500); -//@41 sim_activate(uptr, 200); } break; case 1: @@ -1216,8 +1089,10 @@ t_stat mt_reset(DEVICE *dptr) /* attach the specified file to the tape device */ t_stat mt_attach(UNIT *uptr, CONST char *file) { - uint16 addr = GET_UADDR(uptr->CMD); /* get address of mt device */ - t_stat r; + uint16 chsa = GET_UADDR(uptr->CMD); /* get address of mt device */ + DEVICE *dptr = get_dev(uptr); /* get device pointer */ + t_stat r; + DIB *dibp = 0; /* mount the specified file to the MT */ if ((r = sim_tape_attach(uptr, file)) != SCPE_OK) { @@ -1228,7 +1103,20 @@ t_stat mt_attach(UNIT *uptr, CONST char *file) uptr->CMD &= ~0xffff; /* clear out the flags but leave ch/sa */ uptr->POS = 0; /* clear position data */ uptr->SNS = 0; /* clear sense data */ - set_devattn(addr, SNS_DEVEND); /* ready int???? */ + + /* check for valid configured tape */ + /* must have valid DIB and Channel Program pointer */ + dibp = (DIB *)dptr->ctxt; /* get the DIB pointer */ + if ((dib_unit[chsa] == NULL) || (dibp == NULL) || (dibp->chan_prg == NULL)) { + sim_debug(DEBUG_CMD, dptr, + "ERROR===ERROR\nMT device %s not configured on system, aborting\n", + dptr->name); + printf("ERROR===ERROR\nMT device %s not configured on system, aborting\n", + dptr->name); + detach_unit(uptr); /* detach if error */ + return SCPE_UNATT; /* error */ + } + set_devattn(chsa, SNS_DEVEND); /* ready int???? */ return SCPE_OK; /* return good status */ } diff --git a/SEL32/sel32_scfi.c b/SEL32/sel32_scfi.c index a84dbcf..122a02c 100644 --- a/SEL32/sel32_scfi.c +++ b/SEL32/sel32_scfi.c @@ -223,7 +223,7 @@ scfi_type[] = /* Class F Disc Devices */ /* MPX SCSI disks for SCFI controller */ {"MH1GB", 1, 192, 40, 34960, 34960, 0x40}, /*0 69920 1000M */ - {"SG038", 1, 192, 20, 2190, 2190, 0x40}, /*1 21900 38M */ + {"SG038", 1, 192, 20, 21900, 21900, 0x40}, /*1 21900 38M */ {"SG120", 1, 192, 40, 34970, 34970, 0x40}, /*2 69940 1200M */ {"SG076", 1, 192, 20, 46725, 46725, 0x40}, /*3 46725 760M */ {NULL, 0} @@ -550,11 +550,7 @@ t_stat scfi_srv(UNIT *uptr) sim_debug(DEBUG_CMD, dptr, "scfi_srv cmd INCH chsa %04x addr %06x count %04x completed\n", chsa, mema, chp->ccw_count); -#ifdef FIX4MPX - chan_end(chsa, SNS_CHNEND); /* return just channel end OK */ -#else chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* return OK */ -#endif } break; @@ -746,7 +742,6 @@ rezero: trk = (uptr->CHS >> 8) & 0xff; /* get trk/head */ sec = uptr->CHS & 0xff; /* get sec */ /* get sector offset */ -// tstart = STAR2SEC(uptr->STAR, SPT(type), SPC(type)); tstart = STAR2SEC(uptr->CHS, SPT(type), SPC(type)); /* read in a sector of data from disk */ @@ -783,8 +778,7 @@ rezero: tstart++; /* bump to next sector */ /* convert sect back to chs value */ uptr->CHS = scfisec2star(tstart, type); - /* see of over end of disk */ -// if (tstart >= CAPB(type)) { + /* see if over end of disk */ if (tstart >= CAP(type)) { /* EOM reached, abort */ sim_debug(DEBUG_CMD, dptr, @@ -830,7 +824,6 @@ rddone: trk = (uptr->CHS >> 8) & 0xff; /* get trk/head */ sec = uptr->CHS & 0xff; /* get sec */ /* get sector offset */ -// tstart = STAR2SEC(uptr->STAR, SPT(type), SPC(type)); tstart = STAR2SEC(uptr->CHS, SPT(type), SPC(type)); /* process the next sector of data */ @@ -877,8 +870,7 @@ rddone: tstart++; /* bump to next sector */ /* convert sect back to chs value */ uptr->CHS = scfisec2star(tstart, type); - /* see of over end of disk */ -// if (tstart >= CAPB(type)) { + /* see if over end of disk */ if (tstart >= CAP(type)) { /* EOM reached, abort */ sim_debug(DEBUG_CMD, dptr, @@ -900,7 +892,6 @@ wrdone: sim_debug(DEBUG_CMD, dptr, "invalid command %02x unit %02x\n", cmd, unit); uptr->SNS |= SNS_CMDREJ; uptr->CMD &= ~(0xffff); /* remove old status bits & cmd */ -// chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); return SNS_CHNEND|STATUS_PCHK; break; } @@ -932,7 +923,6 @@ t_stat scfi_reset(DEVICE * dptr) /* create the disk file for the specified device */ int scfi_format(UNIT *uptr) { -// struct ddata_t *data = (struct ddata_t *)uptr->up7; uint16 addr = GET_UADDR(uptr->CMD); int type = GET_TYPE(uptr->flags); DEVICE *dptr = get_dev(uptr); @@ -940,7 +930,6 @@ int scfi_format(UNIT *uptr) { uint32 tsize = scfi_type[type].spt; /* get track size in sectors */ uint32 csize = scfi_type[type].nhds * tsize; /* get cylinder size in sectors */ uint32 cyl = scfi_type[type].cyl; /* get # cyl */ -// uint16 spc = scfi_type[type].nhds * scfi_type[type].spt; /* sectors/cyl */ uint32 cap = scfi_type[type].cyl * csize; /* disk capacity in sectors */ uint32 cylv = cyl; /* number of cylinders */ uint8 *buff; @@ -992,15 +981,15 @@ int scfi_format(UNIT *uptr) { return 1; } free(buff); /* free cylinder buffer */ - set_devattn(addr, SNS_DEVEND); /* start us up */ return 0; } /* attach the selected file to the disk */ t_stat scfi_attach(UNIT *uptr, CONST char *file) { - uint16 addr = GET_UADDR(uptr->CMD); + uint16 chsa = GET_UADDR(uptr->CMD); int type = GET_TYPE(uptr->flags); DEVICE *dptr = get_dev(uptr); + DIB *dibp = 0; t_stat r; uint32 ssize; /* sector size in bytes */ uint8 buff[1024]; @@ -1060,7 +1049,19 @@ fmt: sim_debug(DEBUG_CMD, &sda_dev, "File %s attached to %s\r\n", file, scfi_type[type].name); - set_devattn(addr, SNS_DEVEND); + /* check for valid configured disk */ + /* must have valid DIB and Channel Program pointer */ + dibp = (DIB *)dptr->ctxt; /* get the DIB pointer */ + if ((dib_unit[chsa] == NULL) || (dibp == NULL) || (dibp->chan_prg == NULL)) { + sim_debug(DEBUG_CMD, dptr, + "ERROR===ERROR\nSCFI device %s not configured on system, aborting\n", + dptr->name); + printf("ERROR===ERROR\nSCFI device %s not configured on system, aborting\n", + dptr->name); + detach_unit(uptr); /* detach if error */ + return SCPE_UNATT; /* error */ + } + set_devattn(chsa, SNS_DEVEND); return SCPE_OK; } @@ -1118,8 +1119,7 @@ t_stat scfi_get_type(FILE * st, UNIT *uptr, int32 v, CONST void *desc) } /* help information for disk */ -t_stat scfi_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, - const char *cptr) +t_stat scfi_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr) { int i; fprintf (st, "SEL-32 SCFI Disk Processor\r\n"); @@ -1148,5 +1148,4 @@ const char *scfi_description (DEVICE *dptr) { return "SEL-32 SCFI Disk Processor"; } - #endif diff --git a/SEL32/sel32_scsi.c b/SEL32/sel32_scsi.c index 33d3527..598fc7b 100644 --- a/SEL32/sel32_scsi.c +++ b/SEL32/sel32_scsi.c @@ -524,7 +524,6 @@ t_stat scsi_srv(UNIT *uptr) CHANP *chp = (CHANP *)dibp->chan_prg; /* get pointer to channel program */ int cmd = uptr->CMD & DSK_CMDMSK; int type = GET_TYPE(uptr->flags); -// uint32 trk, cyl, sec; int unit = (uptr - dptr->units); int bufnum = GET_DEV_BUF(dptr->flags); int len=0; @@ -556,9 +555,6 @@ t_stat scsi_srv(UNIT *uptr) case DSK_INCH2: /* use 0xF0 for inch, just need int */ { uint32 mema; /* memory address */ -// uint32 daws[8]; /* drive attribute registers */ -// uint32 i, j; -// uint32 i; len = chp->ccw_count; /* INCH command count */ mema = chp->ccw_addr; /* get inch or buffer addr */ @@ -588,9 +584,6 @@ t_stat scsi_srv(UNIT *uptr) "scsi_srv cmd INCH chsa %04x addr %06x count %04x completed\n", chsa, mema, chp->ccw_count); chan_end(chsa, SNS_CHNEND|SNS_DEVEND); /* return OK */ -#ifdef DO_DYNAMIC_DEBUG - cpu_dev.dctrl |= (DEBUG_INST | DEBUG_CMD | DEBUG_EXP | DEBUG_IRQ); -#endif } break; @@ -763,7 +756,6 @@ t_stat scsi_srv(UNIT *uptr) /* calculate file position in bytes of requested sector */ /* file offset in bytes */ tstart = uptr->STAR * SSB(type); -// uptr->CHS = uptr->STAR; sim_debug(DEBUG_DETAIL, dptr, "scsi_srv seek start %04x sector %06x\n", @@ -1075,8 +1067,6 @@ t_stat scsi_srv(UNIT *uptr) case DSK_TCMD: /* Transfer command packet 0xD3 */ { uint32 mema; /* memory address */ -// uint32 daws[8]; /* drive attribute registers */ -// uint32 i, j; int32 i; uptr->SNS &= ~SNS_TCMD; /* show not presessing TCMD cmd chain */ @@ -1093,11 +1083,11 @@ t_stat scsi_srv(UNIT *uptr) #ifdef NOTNOW if (len != 36) { - /* we have invalid count, error, bail out */ - uptr->CMD &= LMASK; /* remove old status bits & cmd */ - uptr->SNS |= SNS_CMDREJ|SNS_EQUCHK; - chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); - break; + /* we have invalid count, error, bail out */ + uptr->CMD &= LMASK; /* remove old status bits & cmd */ + uptr->SNS |= SNS_CMDREJ|SNS_EQUCHK; + chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); + break; } #endif @@ -1135,7 +1125,6 @@ t_stat scsi_srv(UNIT *uptr) sim_debug(DEBUG_CMD, dptr, "invalid command %02x unit %02x\n", cmd, unit); uptr->SNS |= SNS_CMDREJ; uptr->CMD &= LMASK; /* remove old status bits & cmd */ -// chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); return SNS_CHNEND|STATUS_PCHK; break; } @@ -1195,18 +1184,14 @@ int scsi_format(UNIT *uptr) { /* get sector address of utx diag map (DMAP) track 0 pointer */ /* put data = 0xf0000000 + (cyl-1), 0x8a000000 + daddr, */ /* 0x9a000000 + (cyl-1), 0xf4000008 */ -//WASint32 daddr = vaddr - SPT(type); int32 daddr = (CYL(type)-4) * SPC(type) + (HDS(type)-2) * SPT(type); /* get sector address of utx flaw data (1 track long) */ /* set trace data to zero */ -//WASint32 faddr = daddr - SPT(type); int32 faddr = (CYL(type)-4) * SPC(type) + (HDS(type)-3) * SPT(type); /* get sector address of utx flaw map sec 1 pointer */ /* use this address for sec 1 label pointer */ -//WASint32 uaddr = daddr - SPT(type); -//WASint32 uaddr = daddr - (2*SPT(type)); int32 uaddr = (CYL(type)-4) * SPC(type) + (HDS(type)-4) * SPT(type); /* last user block available */ @@ -1242,12 +1227,10 @@ int scsi_format(UNIT *uptr) { /* defect map */ uint32 dmap[4] = {0xf0000000 | (cap-1), 0x8a000000 | daddr, 0x9a000000 | (cap-1), 0xf4000000}; -//TRY 0x9a000000 | (cap-1), 0xf4000008}; /* utx flaw map */ uint32 fmap[4] = {0xf0000000 | (cap-1), 0x8a000000 | daddr, 0x9a000000 | ltaddr, 0xf4000000}; -//TRY 0x9a000000 | ltaddr, 0xf4000008}; /* see if user wants to initialize the disk */ if (!get_yn("Initialize disk? [Y] ", TRUE)) { @@ -1412,9 +1395,10 @@ int scsi_format(UNIT *uptr) { /* attach the selected file to the disk */ t_stat scsi_attach(UNIT *uptr, CONST char *file) { - uint16 addr = GET_UADDR(uptr->CMD); + uint16 chsa = GET_UADDR(uptr->CMD); int type = GET_TYPE(uptr->flags); DEVICE *dptr = get_dev(uptr); + DIB *dibp = 0; t_stat r; uint32 ssize; /* sector size in bytes */ uint8 buff[1024]; @@ -1432,7 +1416,7 @@ t_stat scsi_attach(UNIT *uptr, CONST char *file) { ssize = SSB(type); /* get sector size in bytes */ sim_debug(DEBUG_CMD, dptr, "Disk %s %04x cyl %d hds %d sec %d ssiz %d capacity %d\n", - scsi_type[type].name, addr, scsi_type[type].cyl, scsi_type[type].nhds, + scsi_type[type].name, chsa, scsi_type[type].cyl, scsi_type[type].nhds, scsi_type[type].spt, ssize, uptr->capac); /* disk capacity */ @@ -1468,13 +1452,25 @@ fmt: sim_debug(DEBUG_CMD, dptr, "Attach %s %04x cyl %d hds %d spt %d spc %d cap sec %d cap bytes %d\n", - scsi_type[type].name, addr, CYL(type), HDS(type), SPT(type), SPC(type), + scsi_type[type].name, chsa, CYL(type), HDS(type), SPT(type), SPC(type), CAP(type), CAPB(type)); - sim_debug(DEBUG_CMD, dptr, "File %s at addr %04x attached to %s\r\n", - file, addr, scsi_type[type].name); + sim_debug(DEBUG_CMD, dptr, "File %s at chsa %04x attached to %s\r\n", + file, chsa, scsi_type[type].name); - set_devattn(addr, SNS_DEVEND); + /* check for valid configured disk */ + /* must have valid DIB and Channel Program pointer */ + dibp = (DIB *)dptr->ctxt; /* get the DIB pointer */ + if ((dib_unit[chsa] == NULL) || (dibp == NULL) || (dibp->chan_prg == NULL)) { + sim_debug(DEBUG_CMD, dptr, + "ERROR===ERROR\nSCSI device %s not configured on system, aborting\n", + dptr->name); + printf("ERROR===ERROR\nSCSI device %s not configured on system, aborting\n", + dptr->name); + detach_unit(uptr); /* detach if error */ + return SCPE_UNATT; /* error */ + } + set_devattn(chsa, SNS_DEVEND); return SCPE_OK; } diff --git a/SEL32/sel32_sys.c b/SEL32/sel32_sys.c index f70733b..eadf3d6 100644 --- a/SEL32/sel32_sys.c +++ b/SEL32/sel32_sys.c @@ -668,7 +668,6 @@ t_opcode optab[] = { { 0x2C0E, 0xFC0F, H|TYPE_F, "TRSC", }, /* Transfer Register to Scratchpad # * */ { 0x2C0F, 0xFC0F, H|TYPE_F, "TSCR", }, /* Transfer Scratchpad to Register # * */ { 0x3000, 0xFC0F, X|H|TYPE_F, "CALM", }, /* Call Monitor 32/55 # */ -//FF{ 0x3400, 0xFC08, N|TYPE_D, "LA", }, /* Load Address NBR Note! FW instruction */ { 0x3400, 0xFC00, N|TYPE_D, "LA", }, /* Load Address NBR Note! FW instruction */ { 0x3800, 0xFC0F, H|TYPE_F, "ADR", }, /* Add Register to Register # */ { 0x3801, 0xFC0F, H|TYPE_F, "ADRFW", }, /* Add Floating Point to Register # */ @@ -873,7 +872,6 @@ int fprint_inst(FILE *of, uint32 val, int32 sw) fputc(' ', of); if (mode) { /* base reg mode */ -//UTX fprint_val(of, val&0xffff, 16, 16, PV_RZRO); /* output 16 bit offset */ fprint_val(of, val&0xffff, 16, 16, PV_LEFT); /* output 16 bit offset */ if (inst & 07) { fputc('(', of); @@ -881,8 +879,6 @@ int fprint_inst(FILE *of, uint32 val, int32 sw) fputc(('0'+(inst & 07)), of); /* output the base reg number */ fputc(')', of); } -// if (inst & 0x70) { -// if ((inst & 0x70) && (tab->type != TYPE_D)) { if (inst & 0x70) { fputc(',', of); // fputc('R', of); @@ -1029,8 +1025,8 @@ t_stat fprint_sym (FILE *of, t_addr addr, t_value *val, UNIT *uptr, int32 sw) rdx = 16; /* hex */ if (sw & SWMASK ('M')) { /* machine base mode? */ -// sw &= ~ SWMASK('F'); /* Can't do F and M at same time */ -// sw &= ~ SWMASK('W'); /* Can't do W and M at same time */ +// sw &= ~ SWMASK('F'); /* Can't do F and M at same time */ +// sw &= ~ SWMASK('W'); /* Can't do W and M at same time */ sw &= ~ SWMASK('B'); /* Can't do B and M at same time */ sw &= ~ SWMASK('C'); /* Can't do C and M at same time */ if (addr & 0x02) diff --git a/SEL32/tests/diag.ini b/SEL32/tests/diag.ini index 0e1ab20..c4dfb62 100644 --- a/SEL32/tests/diag.ini +++ b/SEL32/tests/diag.ini @@ -187,6 +187,10 @@ set cpu idle ;bo dma0 ; ; Go to simh on completion of script -expect "DOL>"^M +expect "DOL>" ; Boot from mag tape bo mta0 +det all +;rm temptape.tap +;rm output.tap +quit