From 082a83d0eda982672724bbf8d7841b24c993673f Mon Sep 17 00:00:00 2001 From: Richard Cornwell Date: Fri, 29 Dec 2017 23:22:57 -0500 Subject: [PATCH] IBM360: Misc changes to get system working better. Cleaned up channel handling to properly buffer words. End of file handling on DASD records. Added instruction tracing to debug log. --- IBM360/ibm360_chan.c | 164 ++++++++++++++++++++++++------------------- IBM360/ibm360_cpu.c | 37 ++++++++-- IBM360/ibm360_dasd.c | 16 +++-- IBM360/ibm360_sys.c | 1 + 4 files changed, 136 insertions(+), 82 deletions(-) diff --git a/IBM360/ibm360_chan.c b/IBM360/ibm360_chan.c index c986fc2..460e8af 100644 --- a/IBM360/ibm360_chan.c +++ b/IBM360/ibm360_chan.c @@ -141,6 +141,10 @@ find_subchan(uint16 device) { return ((device - subchannels)>>4) & 0xf; } +/* Read a full word into memory. + * Return 1 if fail. + * Return 0 if success. + */ int readfull(int chan, uint32 addr, uint32 *word) { int sk, k; @@ -166,27 +170,94 @@ readfull(int chan, uint32 addr, uint32 *word) { return 0; } -int writefull(int chan, uint32 addr, uint32 *word) { +/* Read a word into the channel buffer. + * Return 1 if fail. + * Return 0 if success. + */ +int +readbuff(int chan) { int sk, k; + uint32 addr = ccw_addr[chan]; if ((addr & AMASK) > MEMSIZE) { chan_status[chan] |= STATUS_PCHK; + chan_byte[chan] = BUFF_CHNEND; + irq_pend = 1; return 1; } sk = (addr >> 24) & 0xff; if (sk != 0) { if ((cpu_dev.flags & PROTECT) == 0) { chan_status[chan] |= STATUS_PROT; + chan_byte[chan] = BUFF_CHNEND; + irq_pend = 1; return 1; } k = key[(addr & 0xfffc00) >> 10]; if ((k & 0x8) != 0 && (k & 0xf0) != sk) { chan_status[chan] |= STATUS_PROT; + chan_byte[chan] = BUFF_CHNEND; + irq_pend = 1; return 1; } } addr &= AMASK; addr >>= 2; - M[addr] = *word; + chan_buf[chan] = M[addr]; + sim_debug(DEBUG_DATA, &cpu_dev, "Channel write %02x %06x %08x %08x '", + chan, ccw_addr[chan] & 0xFFFFFC, chan_buf[chan], ccw_count[chan]); + for(k = 24; k >= 0; k -= 8) { + char ch = ebcdic_to_ascii[(chan_buf[chan] >> k) & 0xFF]; + if (ch < 0x20 || ch == 0xff) + ch = '.'; + sim_debug(DEBUG_DATA, &cpu_dev, "%c", ch); + } + + sim_debug(DEBUG_DATA, & cpu_dev, "'\n"); + return 0; +} + +/* Write channel buffer to memory. + * Return 1 if fail. + * Return 0 if success. + */ +int +writebuff(int chan) { + int sk, k; + uint32 addr = ccw_addr[chan]; + if ((addr & AMASK) > MEMSIZE) { + chan_status[chan] |= STATUS_PCHK; + chan_byte[chan] = BUFF_CHNEND; + irq_pend = 1; + return 1; + } + sk = (addr >> 24) & 0xff; + if (sk != 0) { + if ((cpu_dev.flags & PROTECT) == 0) { + chan_status[chan] |= STATUS_PROT; + chan_byte[chan] = BUFF_CHNEND; + irq_pend = 1; + return 1; + } + k = key[(addr & 0xfffc00) >> 10]; + if ((k & 0x8) != 0 && (k & 0xf0) != sk) { + chan_status[chan] |= STATUS_PROT; + chan_byte[chan] = BUFF_CHNEND; + irq_pend = 1; + return 1; + } + } + addr &= AMASK; + addr >>= 2; + M[addr] = chan_buf[chan]; + sim_debug(DEBUG_DATA, &cpu_dev, "Channel readf %02x %06x %08x %08x '", + chan, ccw_addr[chan] & 0xFFFFFC, chan_buf[chan], ccw_count[chan]); + for(k = 24; k >= 0; k -= 8) { + char ch = ebcdic_to_ascii[(chan_buf[chan] >> k) & 0xFF]; + if (ch < 0x20 || ch == 0xff) + ch = '.'; + sim_debug(DEBUG_DATA, &cpu_dev, "%c", ch); + } + sim_debug(DEBUG_DATA, &cpu_dev, "'\n"); return 0; } @@ -314,21 +385,8 @@ chan_read_byte(uint16 addr, uint8 *data) { } } if (chan_byte[chan] == BUFF_EMPTY) { - if (readfull(chan, ccw_addr[chan], &chan_buf[chan])) { - chan_byte[chan] = BUFF_CHNEND; - irq_pend = 1; + if (readbuff(chan)) return 1; - } - sim_debug(DEBUG_DATA, &cpu_dev, "Channel write %02x %06x %08x %08x '", - chan, ccw_addr[chan], chan_buf[chan], ccw_count[chan]); - for(k = 24; k >= 0; k -= 8) { - char ch = ebcdic_to_ascii[(chan_buf[chan] >> k) & 0xFF]; - if (ch < 0x20 || ch == 0xff) - ch = '.'; - sim_debug(DEBUG_DATA, &cpu_dev, "%c", ch); - } - - sim_debug(DEBUG_DATA, & cpu_dev, "'\n"); chan_byte[chan] = ccw_addr[chan] & 0x3; ccw_addr[chan] += 4 - chan_byte[chan]; } @@ -356,12 +414,16 @@ chan_write_byte(uint16 addr, uint8 *data) { if ((ccw_cmd[chan] & 0x1) != 0) { return 1; } + if (chan_byte[chan] == BUFF_CHNEND) { + if ((ccw_flags[chan] & FLAG_SLI) == 0) { + chan_status[chan] |= STATUS_LENGTH; + } + return 1; + } if (ccw_count[chan] == 0) { - if (chan_byte[chan] != BUFF_CHNEND) { - if (writefull(chan, ccw_addr[chan], &chan_buf[chan])) { - chan_byte[chan] = BUFF_CHNEND; + if (chan_byte[chan] & BUFF_DIRTY) { + if (writebuff(chan)) return 1; - } } if ((ccw_flags[chan] & FLAG_CD) == 0) { chan_byte[chan] = BUFF_CHNEND; @@ -375,42 +437,18 @@ chan_write_byte(uint16 addr, uint8 *data) { if (load_ccw(chan, 1)) return 1; } - if (chan_byte[chan] == BUFF_CHNEND) { - if ((ccw_flags[chan] & FLAG_SLI) == 0) { - chan_status[chan] |= STATUS_LENGTH; - } - return 1; - } if (ccw_flags[chan] & FLAG_SKIP) { ccw_count[chan]--; + chan_byte[chan] = BUFF_EMPTY; if ((ccw_cmd[chan] & 0xf) == CMD_RDBWD) ccw_addr[chan]--; else ccw_addr[chan]++; -// if (ccw_count[chan] == 0) { - // if (ccw_flags[chan] & FLAG_CD) - // return load_ccw(chan, 1); - // else - // chan_byte[chan] = BUFF_CHNEND; - // return 1; - // } return 0; } if (chan_byte[chan] == (BUFF_EMPTY|BUFF_DIRTY)) { - if (writefull(chan, ccw_addr[chan], &chan_buf[chan])) { - chan_byte[chan] = BUFF_CHNEND; - irq_pend = 1; + if (writebuff(chan)) return 1; - } - sim_debug(DEBUG_DATA, &cpu_dev, "Channel read %02x %06x %08x %08x '", - chan, ccw_addr[chan], chan_buf[chan], ccw_count[chan]); - for(k = 24; k >= 0; k -= 8) { - char ch = ebcdic_to_ascii[(chan_buf[chan] >> k) & 0xFF]; - if (ch < 0x20 || ch == 0xff) - ch = '.'; - sim_debug(DEBUG_DATA, &cpu_dev, "%c", ch); - } - sim_debug(DEBUG_DATA, &cpu_dev, "'\n"); if ((ccw_cmd[chan] & 0xf) == CMD_RDBWD) ccw_addr[chan] -= 1 + (ccw_addr[chan] & 0x3); else @@ -418,11 +456,8 @@ chan_write_byte(uint16 addr, uint8 *data) { chan_byte[chan] = BUFF_EMPTY; } if (chan_byte[chan] == BUFF_EMPTY) { - if (readfull(chan, ccw_addr[chan], &chan_buf[chan])) { - chan_byte[chan] = BUFF_CHNEND; - irq_pend = 1; + if (readbuff(chan)) return 1; - } chan_byte[chan] = ccw_addr[chan] & 0x3; } ccw_count[chan]--; @@ -464,21 +499,12 @@ chan_end(uint16 addr, uint8 flags) { if (chan < 0) return; - if (chan_byte[chan] & BUFF_DIRTY) { - int k; - writefull(chan, ccw_addr[chan], &chan_buf[chan]); - chan_byte[chan] = BUFF_EMPTY; - sim_debug(DEBUG_DATA, &cpu_dev, "Channel read %02x %06x %08x %08x '", - chan, ccw_addr[chan], chan_buf[chan], ccw_count[chan]); - for(k = 24; k >= 0; k -= 8) { - char ch = ebcdic_to_ascii[(chan_buf[chan] >> k) & 0xFF]; - if (ch < 0x20 || ch == 0xff) - ch = '.'; - sim_debug(DEBUG_DATA, &cpu_dev, "%c", ch); - } - sim_debug(DEBUG_DATA, &cpu_dev, "'\n"); - } sim_debug(DEBUG_DETAIL, &cpu_dev, "chan_end(%x, %x) %x\n", addr, flags, ccw_count[chan]); + if (chan_byte[chan] & BUFF_DIRTY) { + if (writebuff(chan)) + return; + chan_byte[chan] = BUFF_EMPTY; + } chan_status[chan] |= STATUS_CEND; chan_status[chan] |= ((uint16)flags) << 8; ccw_cmd[chan] = 0; @@ -494,15 +520,15 @@ chan_end(uint16 addr, uint8 flags) { if (chan_status[chan] & (STATUS_DEND|STATUS_CEND)) { chan_byte[chan] = BUFF_NEWCMD; - while ((ccw_flags[chan] & FLAG_CD)) { + while ((ccw_flags[chan] & FLAG_CD)) { if (load_ccw(chan, 1)) break; - if (ccw_count[chan] != 0 && (ccw_flags[chan] & FLAG_SLI) == 0) { + if ((ccw_flags[chan] & FLAG_SLI) == 0) { sim_debug(DEBUG_DETAIL, &cpu_dev, "chan_end length\n"); chan_status[chan] |= STATUS_LENGTH; ccw_flags[chan] = 0; } - } + } } irq_pend = 1; @@ -629,10 +655,6 @@ int haltio(uint16 addr) { } if (dibp->halt_io != NULL) chan_status[chan] = dibp->halt_io(uptr) << 8; -// if (chan_status[chan] & (STATUS_ATTN|STATUS_PCI|STATUS_EXPT|STATUS_CHECK| -// STATUS_PROT|STATUS_CDATA|STATUS_CCNTL|STATUS_INTER| -// STATUS_CHAIN)) -// return 0; return 0; } diff --git a/IBM360/ibm360_cpu.c b/IBM360/ibm360_cpu.c index 752d07b..56e51a0 100644 --- a/IBM360/ibm360_cpu.c +++ b/IBM360/ibm360_cpu.c @@ -351,9 +351,10 @@ int WriteFull(uint32 addr, uint32 data) { return 1; } -// if ((addr & 0xfffff0) == 0xc90 && data == 0x40404040) { -// fprintf(stderr, "Error word\n\r"); -// } + sim_debug(DEBUG_INST, &cpu_dev, "wr fu %08x %08x ", addr, data); + if ((addr & 0xfffffc) == 0x03c80) { + fprintf(stderr, "Error word\n\r"); + } offset = addr & 0x3; addr >>= 2; @@ -420,7 +421,8 @@ int WriteByte(uint32 addr, uint32 data) { storepsw(OPPSW, IRC_ADDR); return 1; } - if ((addr & 0xfffff0) == 0xc90 && data == 0x40) { + sim_debug(DEBUG_INST, &cpu_dev, "wr by %08x %02x ", addr, data); + if ((addr & 0xfffffc) == 0x03c80) { fprintf(stderr, "Error byte\n\r"); } @@ -462,9 +464,10 @@ int WriteHalf(uint32 addr, uint32 data) { return 1; } -// if ((addr & 0xfffff0) == 0xc90 && data == 0x4040) { -// fprintf(stderr, "Error half\n\r"); -// } + sim_debug(DEBUG_INST, &cpu_dev, "wr hf %08x %04x ", addr, data); + if ((addr & 0xfffffc) == 0x03c80) { + fprintf(stderr, "Error half\n\r"); + } offset = addr & 0x3; addr >>= 2; @@ -607,6 +610,8 @@ wait_loop: ilc = 1; if (hst_lnt) hst[hst_p].inst[0] = src1; + if ((PC & 0xFFFFF0) != 0xBA0) + sim_debug(DEBUG_INST, &cpu_dev, "%08x %04x ", PC, src1 & 0xFFFF); PC += 2; pmsk &= ~ILMASK; reg = (uint8)(src1 & 0xff); @@ -622,6 +627,8 @@ wait_loop: PC += 2; if (hst_lnt) hst[hst_p].inst[1] = addr1; + if ((PC & 0xFFFFF0) != 0xBA0) + sim_debug(DEBUG_INST, &cpu_dev, "%04x ", addr1 & 0xFFFF); /* Check if SS */ if ((op & 0xc0) == 0xc0) { pmsk += 0x40; @@ -631,9 +638,13 @@ wait_loop: ilc = 3; if (hst_lnt) hst[hst_p].inst[2] = addr2; + if ((PC & 0xFFFFF0) != 0xBA0) + sim_debug(DEBUG_INST, &cpu_dev, "%04x ", addr2 & 0xFFFF); } } + if ((PC & 0xFFFFF0) != 0xBA0) + sim_debug(DEBUG_INST, &cpu_dev, " -> "); /* Add in history here */ opr: if (op & 0xc0) { @@ -716,6 +727,8 @@ opr: hst[hst_p].src2 = src2; } + if ((PC & 0xFFFFF0) != 0xBA0) + sim_debug(DEBUG_INST, &cpu_dev, "%08x %08x - %08x %08x\n", addr1, addr2, src1, src2); /* Preform opcode */ switch (op) { case OP_SPM: @@ -1382,6 +1395,8 @@ save_dbl: } else { dest = src1; } + if ((PC & 0xFFFFF0) != 0xBA0) + sim_debug(DEBUG_INST, &cpu_dev, "%02x ", dest); //fprintf(stderr, " %x -> %x", src1, dest); if (WriteByte(addr1, dest)) break; @@ -1390,6 +1405,7 @@ save_dbl: reg--; } while (reg != 0xff); //fprintf(stderr, "\n\r"); + sim_debug(DEBUG_INST, &cpu_dev, "\n"); break; case OP_CLC: @@ -1990,6 +2006,13 @@ save_dbl: hst[hst_p].cc = cc; } + if ((PC & 0xFFFFF0) != 0xBA0) { + sim_debug(DEBUG_INST, &cpu_dev, "R0=%08x R1=%08x R2=%08x R3=%08x ", regs[0], regs[1], regs[2], regs[3]); + sim_debug(DEBUG_INST, &cpu_dev, "R4=%08x R5=%08x R6=%08x R7=%08x\n", regs[4], regs[5], regs[6], regs[7]); + sim_debug(DEBUG_INST, &cpu_dev, "R8=%08x R9=%08x RA=%08x RB=%08x ", regs[8], regs[9], regs[10], regs[11]); + sim_debug(DEBUG_INST, &cpu_dev, "RC=%08x RD=%08x RE=%08x RF=%08x\n", regs[12], regs[13], regs[14], regs[15]); +} + if (irqaddr != 0) { supress: src1 = M[irqaddr>>2]; diff --git a/IBM360/ibm360_dasd.c b/IBM360/ibm360_dasd.c index 7a24e96..f252f2b 100644 --- a/IBM360/ibm360_dasd.c +++ b/IBM360/ibm360_dasd.c @@ -1007,7 +1007,7 @@ index: case DK_RD_CKD: /* Read count, key and data */ /* Wait for any count */ - if (count == 0 && state == DK_POS_CNT) { + if (count == 0 && state == DK_POS_CNT && data->rec != 0) { uptr->u3 |= DK_PARAM; uptr->u3 &= ~DK_INDEX; sim_debug(DEBUG_DETAIL, dptr, "RD CKD unit=%d %d k=%d d=%d %02x %04x\n", @@ -1040,9 +1040,9 @@ index: rd: if (uptr->u3 & DK_PARAM) { /* Check for end of file */ - if (state == DK_POS_DATA && count == 0 && data->dlen == 0) { - sim_debug(DEBUG_DETAIL, dptr, "RD EOF unit=%d %x %d %d\n", - unit, state, count, data->rec); + if (state == DK_POS_DATA && data->dlen == 0) { + sim_debug(DEBUG_DETAIL, dptr, "RD EOF unit=%d %x %d %d d=%d\n", + unit, state, count, data->rec, data->dlen); uptr->u3 &= ~(0xff|DK_PARAM); chan_end(addr, SNS_CHNEND|SNS_DEVEND|SNS_UNITEXP); break; @@ -1230,6 +1230,14 @@ wrckd: uptr->u3 &= ~(0xff|DK_PARAM); chan_end(addr, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); break; + } else if ((cmd == DK_WR_KD || cmd == DK_WR_D) && state == DK_POS_DATA + && data->dlen == 0) { + sim_debug(DEBUG_DETAIL, dptr, "WR EOF unit=%d %x %d %d d=%d\n", + unit, state, count, data->rec, data->dlen); + uptr->u3 &= ~(0xff|DK_PARAM); + uptr->u6 = cmd; + chan_end(addr, SNS_CHNEND|SNS_DEVEND|SNS_UNITEXP); + break; } else if (state == DK_POS_DATA && data->count == data->dlen) { uptr->u6 = cmd; uptr->u3 &= ~(0xff|DK_PARAM); diff --git a/IBM360/ibm360_sys.c b/IBM360/ibm360_sys.c index bdea6c8..20d2079 100644 --- a/IBM360/ibm360_sys.c +++ b/IBM360/ibm360_sys.c @@ -85,6 +85,7 @@ DEBTAB dev_debug[] = { {"DETAIL", DEBUG_DETAIL, "Show details about device"}, {"EXP", DEBUG_EXP, "Show exception information"}, {"POS", DEBUG_POS, "Dasd positioning information"}, + {"INST", DEBUG_INST, "Show instruction execution"}, {0, 0} };