From 18175040523db4d6195d1d32696d4c2178490c11 Mon Sep 17 00:00:00 2001 From: Mark Pizzolato Date: Mon, 3 Nov 2014 15:48:25 -0800 Subject: [PATCH] PDQ-3: Latest update from Holger Veit - removed cycle counting in CPU, the sim_interval issue - fixed the Console multiplexer logic; it now works with SET REMOTE TELNET= and SET CONSOLE TELNET= - commented testhdt.sim - changed run.cmd to try to execute either VStudio or mingw executable, in this order. - changed printf messages to use sim_printf Possible issues remaining: - timer device polling, not yet debugged, the rate of 1.25MHz is likely still incorrect, so UCSD wall clock is surely wrong - few instructions still to be trapped by opcode.debug - I haven't seen them in life code yet - HD device still not yet finished; I'll pick this up again soon --- PDQ-3/pdq3_cpu.c | 176 +++++--------------------------------------- PDQ-3/pdq3_defs.h | 17 +---- PDQ-3/pdq3_stddev.c | 166 ++++++++++++----------------------------- PDQ-3/pdq3_sys.c | 6 +- PDQ-3/run.cmd | 11 ++- PDQ-3/testhdt.sim | 47 ++++++++++-- 6 files changed, 121 insertions(+), 302 deletions(-) diff --git a/PDQ-3/pdq3_cpu.c b/PDQ-3/pdq3_cpu.c index 03f13f96..78efb30e 100644 --- a/PDQ-3/pdq3_cpu.c +++ b/PDQ-3/pdq3_cpu.c @@ -310,7 +310,7 @@ static t_stat rom_ignore(t_addr ea, uint16 data) { t_stat cpu_boot(int32 unitnum, DEVICE *dptr) { t_stat rc; uint16 ctp, ssv, rq; - sim_printf("BOOT CPU\n"); +// sim_printf("BOOT CPU\n"); cpu_reset(dptr); dbg_init(); @@ -343,7 +343,7 @@ void cpu_finishAutoload() { /* CPU reset */ t_stat cpu_reset (DEVICE *dptr) { - sim_printf("CPU RESET\n"); +// sim_printf("CPU RESET\n"); sim_brk_types = SWMASK('E')|SWMASK('R')|SWMASK('W'); sim_brk_dflt = SWMASK('E'); @@ -709,7 +709,7 @@ static void DoCXG(uint8 segno, uint8 procno) { // sim_printf("CXG: ptbl=%x, reg_segb=%x\n",ptbl,reg_segb); reg_ipc = createMSCW(ptbl, procno, reg_bp, osegno, osegb); /* call new segment */ - sim_interval -= 63; /* actually 63.2 */ + sim_interval--; } static t_stat Raise(uint16 err) { @@ -788,7 +788,7 @@ static uint16 enque(uint16 qhead, uint16 qtask) { /* perform a task switch. If no task ready to run, wait for an interrupt */ static t_stat taskswitch6() { uint16 vector, sem; - int level; + int level, kbdc; t_stat rc = SCPE_OK; // int kbdc; sim_debug(DBG_CPU_CONC2, &cpu_dev, DBG_PCFORMAT0 "Taskswitch6: ctp=$%04x rq=$%04x\n",DBG_PC, reg_ctp, reg_rq); @@ -804,7 +804,6 @@ static t_stat taskswitch6() { rc = DoSIGNAL(sem); return rc; } else { -#if 0 kbdc = sim_poll_kbd(); /* check keyboard */ if (kbdc == SCPE_STOP) return kbdc; /* handle CTRL-E */ /* process timer */ @@ -812,10 +811,7 @@ static t_stat taskswitch6() { if ((rc = sim_process_event()) != SCPE_OK) return rc; } - sim_interval -= 4; /* actually 3.6, NOP cycle */ -#else sim_idle(TMR_IDLE, TRUE); -#endif } } @@ -864,7 +860,7 @@ static t_stat DoSIGNAL(uint16 sem) { sim_debug(DBG_CPU_CONC3, &cpu_dev, DBG_PCFORMAT0 "SIGNAL: reg_rq=$%x, reg_ctp=$%x\n", DBG_PC, reg_rq, reg_ctp); if (reg_ctp == NIL) { /* no current task (marker for int processing */ - sim_interval -= 135; /* actually 134.8, consume time */ + sim_interval--; /* consume time */ return taskswitch6(); /* and switch task */ } if (Getb(reg_ctp+OFFB_PRIOR,0) < Getb(qtask+OFFB_PRIOR,0)) { /* is qtask higher prio than current task? */ @@ -873,7 +869,7 @@ static t_stat DoSIGNAL(uint16 sem) { } else { /* else: nothing is waiting on this semaphore, discard argument, and continue */ reg_sp++; - sim_interval -= 52; /* correct: 52.0 */ + sim_interval--; } return rc; } @@ -882,11 +878,11 @@ static t_stat DoSIGNAL(uint16 sem) { sim_debug(DBG_CPU_CONC2, &cpu_dev, DBG_PCFORMAT0 "SIGNAL: Sem=$%x(count=%d): increment\n",DBG_PC, sem, count); Put(sem+OFF_SEMCOUNT,count+1); if (reg_ctp == NIL) { /* if no active task, get one from ready queue */ - sim_interval -= 135; /* actually 134.8 */ + sim_interval--; return taskswitch6(); } reg_sp++; - sim_interval -= 18; /* correct: 18.0 */ + sim_interval--; return rc; } @@ -905,14 +901,14 @@ static t_stat DoWAIT(uint16 sem) { // sim_debug(DBG_CPU_CONC3, &cpu_dev, DBG_PCFORMAT0 "WAIT: new qhead=%x\n",DBG_PC, qhead); rc = taskswitch5(); /* save context in TIB, and switch to new task from ready queue */ - sim_interval -= 91; /* actually 90.8 */ + sim_interval--; sim_debug(DBG_CPU_CONC2, &cpu_dev, DBG_PCFORMAT0 "WAIT: DONE, switch to newTIB=$%04x\n",DBG_PC, reg_ctp); return rc; } else { sim_debug(DBG_CPU_CONC2, &cpu_dev, DBG_PCFORMAT0 "WAIT: Sem=$%04x(count=%d): decrement\n", DBG_PC, sem, count); Put(sem+OFF_SEMCOUNT,count-1); } - sim_interval -= 12; /* actually 11.6 */ + sim_interval--; sim_debug(DBG_CPU_CONC2, &cpu_dev, DBG_PCFORMAT0 "WAIT: DONE, continue\n",DBG_PC); return SCPE_OK; } @@ -933,7 +929,6 @@ static t_stat DoInstr(void) { uint8 ub1, ub2; uint8 segno, osegno, procno; float tf1, tf2; - double cyc = 0.0; int i; /* set PCX: current instr in progress */ @@ -959,229 +954,179 @@ static t_stat DoInstr(void) { case 0x18: case 0x19: case 0x1a: case 0x1b: case 0x1c: case 0x1d: case 0x1e: case 0x1f: /* SLDCi */ Push(opcode & 0x1f); - cyc = 2.8; break; case 0x98: /* LDCN */ Push(NIL); - cyc = 6.4; break; case 0x80: /* LDCB */ Push(UB()); - cyc = 5.6; break; case 0x81: /* LDCI */ Push(W()); - cyc = 8.4; break; case 0x82: /* LCA */ Push(reg_segb + B()); - cyc = 8.0; break; case 0x20: case 0x21: case 0x22: case 0x23: case 0x24: case 0x25: case 0x26: case 0x27: case 0x28: case 0x29: case 0x2a: case 0x2b: case 0x2c: case 0x2d: case 0x2e: case 0x2f: /* SLDLi */ Push(Get(reg_mp + MSCW_SZ + (opcode & 0x0f))); - cyc = 6.4; break; case 0x87: /* LDL */ Push(Get(reg_mp + MSCW_SZ -1 + B())); - cyc = 9.6; break; case 0x84: /* LLA */ Push(reg_mp + MSCW_SZ -1 + B()); - cyc = 7.6; break; case 0xa4: /* STL */ Put(reg_mp + MSCW_SZ -1 + B(), Pop()); - cyc = 9.6; break; case 0x30: case 0x31: case 0x32: case 0x33: case 0x34: case 0x35: case 0x36: case 0x37: case 0x38: case 0x39: case 0x3a: case 0x3b: case 0x3c: case 0x3d: case 0x3e: case 0x3f: /* SLDOi */ Push(Get(reg_bp + MSCW_SZ + (opcode & 0x0f))); - cyc = 7.2; break; case 0x85: /* LDO */ Push(Get(reg_bp + MSCW_SZ -1 + B())); - cyc = 10.0; break; case 0x86: /* LAO */ Push(reg_bp + MSCW_SZ -1 + B()); - cyc = 8.0; break; case 0xa5: /* SRO */ Put(reg_bp + MSCW_SZ -1 + B(),Pop()); - cyc = 13.2; break; case 0x89: /* LOD */ - db = DB(); - reg_lm = TraverseMSstat(db); + reg_lm = TraverseMSstat(DB()); Push(Get(reg_lm + MSCW_SZ -1 + B())); - cyc = 17.2 + 3.2*db; break; case 0x88: /* LDA */ - db = DB(); - reg_lm = TraverseMSstat(db); + reg_lm = TraverseMSstat(DB()); Push(reg_lm + MSCW_SZ -1 + B()); - cyc = 15.2 + 3.2*db; break; case 0xa6: /* STR */ - db = DB(); - reg_lm = TraverseMSstat(db); + reg_lm = TraverseMSstat(DB()); Put(reg_lm + MSCW_SZ -1 + B(),Pop()); - cyc = 16.8 * 3.2*db; break; case 0xc4: /* STO */ t1 = Pop(); Put(Pop(),t1); - cyc = 8.0; break; case 0x9a: /* LDE */ t2 = GetSegbase(UB()); Push(Get(t2 + B())); - cyc = 26.8; break; case 0x9b: /* LAE */ ub1 = UB(); Push(GetSegbase(ub1) + B()); - cyc = 24.8; break; case 0xd9: /* STE */ ub1 = UB(); Put(GetSegbase(ub1) + B(), Pop()); - cyc = 26.0; break; case 0x83: /* LDC */ b = B(); ub1 = UB(); src = reg_segb + b + ub1; for (i=1; i<=ub1; i++) Put(reg_sp-i,Get(src-i)); reg_sp -= ub1; - cyc = 18.0 + 4.0*ub1; break; case 0xd0: /* LDM */ ub1 = UB(); src = Pop() + ub1; for (i=1; i<=ub1; i++) Put(reg_sp-i,Get(src-i)); reg_sp -= ub1; - cyc = 10.4 + 6.0*ub1; break; case 0x8e: /* STM */ ub1 = UB(); dst = Get(reg_sp+ub1); for (i=0; i<=(ub1-1); i++) Put(dst+i,Pick(i)); reg_sp += (ub1+1); - cyc = 12.4 + 6.0*ub1; break; case 0xa7: /* LDB */ b = Pop(); Push(Getb(Pop(), b)); - cyc = 12.0; break; case 0xc8: /* STB */ ub1 = Pop() & 0xff; /* index */ b = Pop(); /* byteaddr */ Putb(Pop(), b, ub1); - cyc = 13.6; break; case 0xc5: /* MOV */ b = B(); src = Pop(); dst = Pop(); for (i=0; i<=(b-1); i++) Put(dst+i,Get(src+i)); - cyc = 13.2 + 6.0*b; break; case 0x78: case 0x79: case 0x7a: case 0x7b: case 0x7c: case 0x7d: case 0x7e: case 0x7f: /* SINDi */ Push(Get(Pop() + (opcode & 0x07))); - cyc = 8.4; break; case 0xe6: /* IND */ Push(Get(Pop() + B())); - cyc = 12.4; break; case 0xe7: /* INC */ Push(Pop() + B()); - cyc = 9.6; break; case 0xd7: /* IXA */ b = B(); t1 = Pop(); Push(Pop() + t1*b); - cyc = 9.6 + b/16384.*46.4; break; case 0xd8: /* IXP */ ub1 = UB(); ub2 = UB(); inx = Pop(); Push(Pop() + inx / ub1); Push(ub2); Push((inx % ub1) * ub2); - cyc = 35.6; /* inaccurate */ break; case 0xc9: /* LDP */ t1 = Pop(); /*start*/ t2 = Pop(); /*nbits*/ /* Bogus warning: WD9693_PasIII_OSref_Jul82 is wrong here: * (sp+2) is an address not a value, so must be dereferenced first */ Push((Get(Pop() /*addr*/) & GetMask(t1,t2)) >> t1); - cyc = 18.4 + 2.0*(t1+t2); break; case 0xca: /* STP */ t4 = Pop(); /*data*/ t1 = Pop(); /*start*/ t2 = Pop(); /*nbits*/ t3 = Pop(); /*addr*/ t5 = Get(t3); clrbit(t5,GetMask(t1,t2)); t4 = (t4 & masks[t2]) << t1; Put(t3, t5 | t4); - cyc = 20.4 + 2.0*t2 + 2.8*t1; break; case 0xa1: /* LAND */ Push(Pop() & Pop()); - cyc = 8.0; break; case 0xa0: /* LOR */ Push(Pop() | Pop()); - cyc = 8.0; break; case 0xe5: /* LNOT */ Push(~Pop()); - cyc = 5.2; break; case 0x9f: /* BNOT */ Push((~Pop()) & 1); - cyc = 6.0; break; case 0xb4: /* LEUSW */ t1 = Pop(); t2 = Pop() <= t1 ? 1 : 0; Push(t2); - cyc = t2 ? 9.6 : 10.4; break; case 0xb5: /* GEUSW */ t1 = Pop(); t2 = Pop() >= t1 ? 1 : 0; Push(t2); - cyc = t2 ? 9.6 : 10.4; break; case 0xe0: /* ABI */ ts1 = PopS(); PushS(ts1 < 0 ? -ts1 : ts1); - cyc = ts1 < 0 ? 6.0 : 4.8; break; case 0xe1: /* NGI */ PushS(-PopS()); - cyc = 5.2; break; case 0xe2: /* DUP1 */ Push(Tos()); - cyc = 5.2; break; case 0xa2: /* ADI */ PushS(PopS() + Pop()); - cyc = 8.0; break; case 0xa3: /* SBI */ ts1 = PopS(); PushS(PopS() - ts1); - cyc = 8.0; break; case 0x8c: /* MPI */ PushS(Pop() * Pop()); - cyc = 28.0; /* average */ break; case 0x8d: /* DVI */ ts1 = PopS(); if (ts1 == 0) { Raise(PASERROR_DIVZERO); break; } ts2 = PopS() / ts1; PushS(ts2); - cyc = ts2 == 0 ? 8.4 : (ts2 > 0 ? 89.2 : 91.2); break; case 0x8f: /* MODI */ ts1 = PopS(); if (ts1 <= 0) { Raise(PASERROR_DIVZERO); /* XXX */ break; } ts2 = Pop() % ts1; PushS(ts2); - cyc = ts2 == 0 ? 8.4 : (ts2 > 0 ? 89.2 : 91.2); break; case 0xcb: /* CHK */ t1 = Tos(); t2 = Pick(1); t3 = Pick(2); @@ -1189,102 +1134,81 @@ static t_stat DoInstr(void) { reg_sp += 2; else Raise(PASERROR_VALRANGE); - cyc = 14.4; break; case 0xb0: /* EQUI */ t1 = PopS()==PopS() ? 1 : 0; Push(t1); - cyc = t1 ? 9.6 : 10.4; break; case 0xb1: /* NEQI */ t1 = PopS()==PopS() ? 0 : 1; Push(t1); - cyc = t1 ? 9.6 : 10.4; break; case 0xb2: /* LEQI */ ts1 = PopS(); t2 = PopS() <= ts1 ? 1 : 0; Push(t2); - cyc = t2 ? 10.4 : 11.2; break; case 0xb3: /* GEQI */ ts1 = PopS(); t2 = PopS() >= ts1 ? 1 : 0; Push(t2); - cyc = t2 ? 10.4 : 11.2; break; case 0xcc: /* FLT */ t1 = PopS(); PushF((float)t1); - cyc = t1 ? 30.8 : 10.8; break; case 0xbe: /* TNC */ tf1 = PopF(); PushS((int16)tf1); - cyc = tf1 ? (fabs(tf1)<0.5 ? 15.6 : 37.4) : 12.4; /* approximate */ break; case 0xbf: /* RND */ tf1 = PopF(); PushS((int16)(tf1+0.5)); - cyc = tf1 ? (fabs(tf1)<0.5 ? 15.6 : 37.4) : 12.4; /* approximate */ break; case 0xe3: /* ABR */ PushF((float)fabs(PopF())); - cyc = 5.2; break; case 0xe4: /* NGR */ PushF(-PopF()); - cyc = 5.2; break; case 0xc0: /* ADR */ tf1 = PopF(); PushF(tf1 + PopF()); - cyc = tf1 ? 106.8 : 18.8; /* average */ break; case 0xc1: /* SBR */ tf1 = PopF(); PushF(PopF() - tf1); - cyc = tf1 ? 110.0 : 19.2; /* average */ break; case 0xc2: /* MPR */ tf1 = PopF(); PushF(tf1 * PopF()); - cyc = tf1 ? 168.6 : 26.4; /* average */ break; case 0xc3: /* DVR */ tf1 = PopF(); if (tf1 == 0) { Raise(PASERROR_DIVZERO); break; } tf2 = PopF(); PushF(tf2 / tf1); - cyc = tf2 ? 217.2 : 32.4; /* average */ break; case 0xcd: /* EQUREAL */ tf1 = PopF(); t1 = tf1==PopF() ? 1 : 0; Push(t1); - cyc = t1 ? 16.4 : (tf1 ? 18.4 : 14.8); /* average */ break; case 0xce: /* LEQREAL */ tf1 = PopF(); tf2 = PopF(); t1 = tf2 <= tf1 ? 1 : 0; Push(t1); - cyc = tf1==tf2 ? 16.4 : (tf1 < tf2 ? 18.2 : 19.4); /* average */ break; case 0xcf: /* GEQREAL */ tf1 = PopF(); tf2 = PopF(); Push(tf2 >= tf1 ? 1 : 0); - cyc = tf1==tf2 ? 16.4 : 18.2; /* average */ break; case 0xc6: /* DUP2 */ Push(Pick(1)); Push(Pick(1)); - cyc = 12.0; break; case 0xc7: /* ADJ */ ub1 = UB(); len0 = Tos(); src = reg_sp+1; dst = reg_sp + len0 - ub1 +1; - cyc = 14.4; if (len0 > ub1) { for (i=1; i<=ub1; i++) Put(dst + ub1 -i, Get(src + ub1 - i)); - cyc = 13.6 + 6.8*ub1; } else { for (i=0; i hi) { reg_sp++; Put(reg_sp,0); - cyc = 18.0; } else { len0 = hi / WORD_SZ +1; reg_sp -= (len0-1); Put(reg_sp,len0); @@ -1309,7 +1232,6 @@ static t_stat DoInstr(void) { Put(t2, src); } } - cyc = t1==1 ? 80.4 : (t1==2 ? 83.2 : (45.6 + 3.6*hi/WORD_SZ + 2.0*((hi+lo)%WORD_SZ))); /*approx*/ } } else Raise(PASERROR_VALRANGE); @@ -1319,7 +1241,6 @@ static t_stat DoInstr(void) { t2 = (0 <= ts1 && ts1 <= (len0*WORD_SZ -1)) ? GetBit(reg_sp+1, ts1) : 0; Put(reg_sp + len0 + 1,t2); reg_sp += (len0+1); - cyc = t2 ? (22.8 + len0 % WORD_SZ) : 18.4; break; case 0xdb: /* UNI */ len0 = Tos(); len1 = Pick(len0 + 1); @@ -1329,14 +1250,12 @@ static t_stat DoInstr(void) { src = reg_sp + 1; dst = reg_sp + len0 + 2; for (i=0; i len0) { src = reg_sp+1; dst = reg_sp+len0 + 2; for (i=0; i len0) { src = reg_sp + 1; dst = reg_sp + len0 + 2; for (i=0; i= max1 ? 1 : 0)); - cyc = 16.0 + 7.6*min1 + 4.0*max1; /* inaccurate */ break; case 0xb7: /* LEQPWR */ len0 = Tos(); len1 = Pick(len0 + 1); i=0; @@ -1425,7 +1335,6 @@ static t_stat DoInstr(void) { } } else i = max1; reg_sp += (len0+len1+1); Put(reg_sp,(i >= max1 ? 1 : 0)); - cyc = 16.0 + 8.4*min1 + 4.0*max1; /* inaccurate */ break; case 0xb8: /* GEQPWR */ len0 = Tos(); len1 = Pick(len0 + 1); i=0; @@ -1444,88 +1353,64 @@ static t_stat DoInstr(void) { } } else i = max1; reg_sp += (len0+len1+1); Put(reg_sp,(i >= max1 ? 1 : 0)); - cyc = 21.6 + 8.4*min1 + 4.0*max1; /* inaccurate */ break; case 0xb9: /* EQUBYT */ b = B(); src = Pop(); dst = Pop(); i = 0; while (i < b && Getb(src,i) == Getb(dst,i)) i++; t1 = i >= b ? 1 : 0; Push(t1); - cyc = t1 ? (19.2 + 5.1*b) : (11.4 + 5.1*i); /* inaccurate */ break; case 0xba: /* LEQBYT */ b = B(); src = Pop(); dst = Pop(); i = 0; while (i < b && Getb(src,i) <= Getb(dst,i)) i++; Push(i >= b ? 1 : 0); - cyc = 18.4 + 10.4*b; /* inaccurate */ break; case 0xbb: /* GEQBYT */ b = B(); src = Pop(); dst = Pop(); i = 0; while (i < b && Getb(src,i) >= Getb(dst,i)) i++; Push(i >= b ? 1 : 0); - cyc = 18.4 + 10.4*b; /* inaccurate */ break; case 0x8a: /* UJP */ b = SB(); reg_ipc += b; - cyc = 12.4; break; case 0xd4: /* FJP */ b = SB(); t1 = Pop(); - cyc = 10.8; - if ((t1 & 1)==0) { + if ((t1 & 1)==0) reg_ipc += b; - cyc += 6.0; - } break; case 0xd2: /* EFJ */ b = SB(); t1 = Pop(); t2 = Pop(); - cyc = 11.8; - if (t2 != t1) { + if (t2 != t1) reg_ipc += b; - cyc += 7.4; - } break; case 0xd3: /* NFJ */ b = SB(); t1 = Pop(); t2 = Pop(); - cyc = 12.0; - if (t2 == t1) { + if (t2 == t1) reg_ipc += b; - cyc += 7.2; - } break; case 0x8b: /* UJPL */ w = W(); reg_ipc += w; - cyc = 12.8; break; case 0xd5: /* FJPL */ w = W(); t1 = Pop(); - cyc = 10.0; - if ((t1 & 1)== 0) { + if ((t1 & 1)== 0) reg_ipc += w; - cyc += 8.8; - } break; case 0xd6: /* XJP */ b = B(); t1 = Pop(); t2 = Get(reg_segb + b); - if (t2 <= t1 && Get(reg_segb + b + 1) >= t1) { + if (t2 <= t1 && Get(reg_segb + b + 1) >= t1) reg_ipc += Get(reg_segb + b + 2 + (t1-t2)); - cyc = 32.0; - } else { - cyc = t1 < t2 ? 29.2 : 34.0; - } break; case 0x90: /* CPL */ procno = UB(); ptbl = GetPtbl(); reg_ipc = createMSCW(ptbl, procno, reg_mp, 0, reg_segb); - cyc = 45.6; break; case 0x91: /* CPG */ procno = UB(); ptbl = GetPtbl(); reg_ipc = createMSCW(ptbl, procno, reg_bp, 0, reg_segb); - cyc = 44.8; break; case 0x92: /* CPI */ db = DB(); procno = UB(); @@ -1537,7 +1422,6 @@ static t_stat DoInstr(void) { for (i=1; i<= db; i++) reg_lm = Get(reg_lm+OFF_MSSTAT); Put(reg_mp+OFF_MSSTAT,reg_lm); /* fix stat link */ - cyc = 53.6 + 3.2*db; break; case 0x93: /* CXL */ segno = UB(); procno = UB(); @@ -1546,7 +1430,6 @@ static t_stat DoInstr(void) { ptbl = SetSEGB(segno); AdjustRefCount(segno, 1); reg_ipc = createMSCW(ptbl, procno, reg_mp, osegno, osegb); - cyc = 64.4; break; case 0x94: /* CXG */ ub1 = UB(); ub2 = UB(); @@ -1562,7 +1445,6 @@ static t_stat DoInstr(void) { reg_lm = reg_mp; for (i=1; i<= db; i++) reg_lm = Get(reg_lm+OFF_MSSTAT); Put(reg_mp+OFF_MSSTAT,reg_lm); /* fix stat link */ - cyc = 73.2 + 3.2*db; break; case 0x97: /* CPF */ t1 = Pop(); reg_lm = Pop(); @@ -1573,7 +1455,6 @@ static t_stat DoInstr(void) { ptbl = SetSEGB(segno); AdjustRefCount(segno, 1); reg_ipc = createMSCW(ptbl, procno, reg_lm, osegno, osegb); - cyc = 75.6; break; case 0x96: /* RPU */ dbg_procleave(); @@ -1587,13 +1468,11 @@ static t_stat DoInstr(void) { (void)SetSEGB(segno); } reg_sp += (b + MSCW_SZ); - cyc = 26.0; break; case 0x99: /* LSL */ db = DB(); reg_lm = reg_mp; for (i=1; i<= db; i++) reg_lm = Get(reg_lm+OFF_MSSTAT); Push(reg_lm); - cyc = 12.4 + 3.2*db; break; case 0xde: /* SIGNAL */ t1 = Pick(0); @@ -1604,12 +1483,8 @@ static t_stat DoInstr(void) { DoWAIT(t1); break; case 0x9d: /* LPR */ w = Tos(); - cyc = 0.0; - if (w >= 0) { + if (w >= 0) save_to_tib(); - cyc = 55.2; - } else - cyc = 8.4; if (w == -3) Put(reg_sp, reg_rq); else if (w == -2) Put(reg_sp, reg_ssv); else if (w == -1) Put(reg_sp, reg_ctp); @@ -1620,7 +1495,6 @@ static t_stat DoInstr(void) { w = (int16)Pick(1); if (w >= -1) save_to_tib(); - cyc = 8.4; if (w == -3) { reg_rq = t1; } else if (w == -2) { @@ -1630,10 +1504,8 @@ static t_stat DoInstr(void) { reg_rq = t1; taskswitch5(); // sim_printf("SPR Taskswitch done reg_ctp=%x reg_rq=%x\n",reg_ctp,reg_rq); - cyc = 53.2; break; /* mustn't fall through reg_sp +=2 */ } else if (w >= 1) { - cyc = 54.8; switch (w) { case OFF_SP: reg_sp = t1; break; case OFF_MP: reg_mp = t1; break; @@ -1649,17 +1521,14 @@ static t_stat DoInstr(void) { break; case 0x9e: /* BPT */ Raise(PASERROR_USERBRK); - cyc = 0; /* added in Raise() -> DoCXG() */ return STOP_BPT; // break; case 0x9c: /* NOP */ - cyc = 3.6; break; case 0xbd: /* SWAP */ t1 = Tos(); Put(reg_sp, Pick(1)); Put(reg_sp+1, t1); - cyc = 12.4; break; default: // Raise(PASERROR_UNIMPL); @@ -1673,7 +1542,7 @@ static t_stat DoInstr(void) { if (dbg_check(opcode, DEBUG_POST)) return STOP_DBGPOST; /* count cycles */ - sim_interval -= (int)(cyc+0.5); + sim_interval--; return SCPE_OK; } @@ -1710,12 +1579,7 @@ t_stat sim_instr(void) if ((rc = DoInstr()) != SCPE_OK) break; } else { -#if 0 - /* waste time by doing a NOP */ - sim_interval -= 4; /* actually 3.6 */ -#else sim_idle(TMR_IDLE, TRUE); -#endif } /* process interrupts diff --git a/PDQ-3/pdq3_defs.h b/PDQ-3/pdq3_defs.h index 9d06c385..0d839d1b 100644 --- a/PDQ-3/pdq3_defs.h +++ b/PDQ-3/pdq3_defs.h @@ -204,9 +204,8 @@ #define CON_TERMUNIT 1 #define CON_POLLFIRST 1 /* immediate */ #define CON_POLLRATE 100 -#define CON_POLLWAIT 12500 -//#define CON_TERMRATE 1300 -#define CON_TERMRATE 300 +#define CON_TPS 100 +#define CON_TERMRATE 100 /* floppy size */ #define FDC_MAX_TRACKS 77 @@ -324,18 +323,6 @@ typedef union flcvt { uint16 i[2]; } T_FLCVT; -/* wrapper structure for terminal multiplexer, - pointer to pointer stored in device->ctxt */ -typedef struct { - int pfirst, prate; /* pollrate first time, later */ - TMLN ldsc; - TMXR desc; - UNIT* term; - UNIT* poll; -} SERMUX; -extern t_stat mux_attach(UNIT*, char*, SERMUX*); -extern t_stat mux_detach(UNIT*, SERMUX*); - /* externals */ extern DEVICE cpu_dev; extern UNIT cpu_unit; diff --git a/PDQ-3/pdq3_stddev.c b/PDQ-3/pdq3_stddev.c index ea0a2ebf..3b2dad2d 100644 --- a/PDQ-3/pdq3_stddev.c +++ b/PDQ-3/pdq3_stddev.c @@ -39,8 +39,6 @@ extern UNIT con_unit[]; static t_stat con_termsvc(UNIT *uptr); static t_stat con_pollsvc(UNIT *uptr); -static t_stat con_attach(UNIT*, char*); -static t_stat con_detach(UNIT*); static t_stat con_reset(DEVICE* dptr); static t_stat tim_reset(DEVICE *dptr); @@ -86,27 +84,6 @@ static uint8 con_status; static uint8 con_xmit; static uint8 con_rcv; -/************************************************************************************************ - * Utilities - ***********************************************************************************************/ -t_stat mux_attach(UNIT* uptr, char* cptr, SERMUX* mux) { - t_stat rc; - mux->desc.ldsc = &mux->ldsc; - if ((rc = tmxr_attach(&mux->desc, uptr, cptr)) == SCPE_OK) { - mux->poll->wait = mux->pfirst; - sim_activate(mux->poll, mux->poll->wait); - } - return rc; -} - -t_stat mux_detach(UNIT* uptr, SERMUX* mux) { - t_stat rc = tmxr_detach(&mux->desc, uptr); - mux->ldsc.rcve = 0; - sim_cancel(mux->poll); - sim_cancel(mux->term); - return rc; -} - /************************************************************************************************ * Onboard Console ***********************************************************************************************/ @@ -125,6 +102,8 @@ UNIT con_unit[] = { { UDATA (&con_pollsvc, UNIT_ATTABLE, 0), CON_POLLRATE, }, { UDATA (&con_termsvc, UNIT_IDLE, 0), CON_TERMRATE, } }; +static UNIT* con_tti = &con_unit[0]; /* shorthand for console input and output units */ +static UNIT* con_tto = &con_unit[1]; REG con_reg[] = { { HRDATA (CTRL1, con_ctrl1, 8) }, @@ -147,16 +126,6 @@ DEBTAB con_dflags[] = { { 0, 0 } }; -SERMUX con_mux[1] = { - { CON_POLLFIRST, /*pfirst*/ - CON_POLLRATE, /*prate*/ - { 0 }, /*ldsc*/ - { 1,0,0,0 }, /*desc*/ - &con_unit[1], /*term*/ - &con_unit[0] /*poll*/ - } -}; - DEVICE con_dev = { "CON", /*name*/ con_unit, /*units*/ @@ -172,9 +141,9 @@ DEVICE con_dev = { NULL, /*deposit*/ &con_reset, /*reset*/ NULL, /*boot*/ - con_attach, /*attach*/ - con_detach, /*detach*/ - &con_ctxt, /*ctxt*/ + NULL, /*attach*/ + NULL, /*detach*/ + &con_ctxt, /*ctxt*/ DEV_DEBUG|DEV_DISABLE, /*flags*/ 0, /*dctrl*/ con_dflags, /*debflags*/ @@ -184,10 +153,8 @@ DEVICE con_dev = { /* bus reset handler */ t_stat con_binit() { - SERMUX *mux = &con_mux[0]; - con_status = CONS_THRE; - if (mux->ldsc.conn) setbit(con_status, CONS_DSR); + setbit(con_status, CONS_DSR); con_ctrl1 = 0; /* no echo, receiver disabled, transmitter disabled */ con_ctrl2 = 0; /* ASYNC mode, 8bits, Clock 1X */ @@ -199,37 +166,33 @@ t_stat con_binit() { /* common handlers */ static t_stat con_reset(DEVICE* dptr) { - int32 wait; - SERMUX * mux = &con_mux[0]; - UNIT *term = mux->term; - UNIT *poll = mux->poll; DEVCTXT* ctxt = (DEVCTXT*)dptr->ctxt; + int32 wait = con_tti->wait = CON_POLLRATE; - wait = poll->wait = CON_POLLWAIT; sim_rtcn_init (wait, TMR_CONPOLL); /* init poll timer */ - - sim_cancel(term); + + sim_cancel(con_tto); /* disable output service */ /* register/deregister I/O handlers */ if (dptr->flags & DEV_DIS) { del_ioh(ctxt->ioi); } else { add_ioh(ctxt->ioi); - poll->buf = 0; - sim_activate (poll, wait); + con_tti->buf = 0; + sim_activate (con_tti, wait); } return con_binit(); } t_stat con_attach(UNIT* uptr, char* cptr) { setbit(con_status, CONS_DSR|CONS_DSC); - return mux_attach(uptr, cptr, &con_mux[0]); + return SCPE_OK; } t_stat con_detach(UNIT* uptr) { clrbit(con_status, CONS_DSR); setbit(con_status, CONS_DSC); - return mux_detach(uptr, &con_mux[0]); + return SCPE_OK; } #define XMITENABLED() (isbitset(con_ctrl1,CONC1_RTS)) @@ -262,79 +225,46 @@ t_stat con_detach(UNIT* uptr) { /* Terminal output service */ t_stat con_termsvc (UNIT *uptr) { - SERMUX *mux = &con_mux[0]; - t_bool isnetwork = (mux->poll->flags & UNIT_ATT); - t_stat rc; - int ch = uptr->buf & 0xff; - -// sim_debug(DBG_CON_SVC, &con_dev, "termsvc: isnetwork=%d\n",isnetwork); - /* TODO? sim_tt_outcvt */ - + t_stat rc = SCPE_OK; + + int ch = sim_tt_outcvt(uptr->buf, TT_GET_MODE(uptr->flags)); if (XMITENABLED()) { /* tranmitter enabled */ - /* attached to a telnet port? */ -// printf("*** Emit: %02x ***\n",uptr->buf & 0xff); - if (isnetwork) { - if ((rc=tmxr_putc_ln(&mux->ldsc, ch)) != SCPE_OK) { - sim_activate(uptr, uptr->wait); - return SCPE_OK; - } else - tmxr_poll_tx(&mux->desc); - } else { - if ((rc=sim_putchar_s(ch)) != SCPE_OK) { - sim_activate(uptr, uptr->wait); - return rc==SCPE_STALL ? SCPE_OK : rc; + if (ch >= 0) { + if ((rc = sim_putchar_s(ch)) != SCPE_OK) { + sim_activate(uptr, uptr->wait); /* did not emit char, reschedule termsvc */ + return rc == SCPE_STALL ? SCPE_OK : rc; } } - setbit(con_status,CONS_THRE); /* set transmitter holding reg empty */ - cpu_assertInt(INT_CONT, TRUE); /* generate an interrupt because of DRQO */ } + uptr->pos = uptr->pos + 1; + setbit(con_status, CONS_THRE); /* set transmitter holding reg empty */ + cpu_assertInt(INT_CONT, TRUE); /* generate an interrupt because of DRQO */ return SCPE_OK; } /* Terminal input service */ t_stat con_pollsvc(UNIT *uptr) { - int32 c, kbdc; - SERMUX *mux = &con_mux[0]; - t_bool isnetwork = (mux->poll->flags & UNIT_ATT); + int32 ch; - uptr->wait = sim_rtcn_calb(mux->prate, TMR_CONPOLL); /* calibrate timer */ - sim_activate (uptr, uptr->wait); /* restart polling */ + uptr->wait = sim_rtcn_calb(CON_TPS, TMR_CONPOLL); /* calibrate timer */ + sim_activate(uptr, uptr->wait); /* restart polling */ - kbdc = sim_poll_kbd(); /* check keyboard */ - if (kbdc == SCPE_STOP) return kbdc; /* handle CTRL-E */ - - /* network-redirected input? */ - if (isnetwork) { - if (tmxr_poll_conn(&mux->desc) >= 0) /* incoming connection */ - mux->ldsc.rcve = 1; - tmxr_poll_rx(&mux->desc); /* poll for input */ - if (!tmxr_rqln(&mux->ldsc)) return SCPE_OK; - /* input ready */ - c = tmxr_getc_ln(&mux->ldsc); - if ((c & TMXR_VALID) == 0) return SCPE_OK; - } else { - c = kbdc; /* use char polled from keyboard */ - if (c < SCPE_KFLAG) return c; /* ignore data if not valid */ - } - - c = sim_tt_inpcvt(c, TT_GET_MODE(uptr->flags)); - uptr->buf = c & 0xff; + if ((ch = sim_poll_kbd()) < SCPE_KFLAG) /* check keyboard */ + return ch; + uptr->buf = (ch & SCPE_BREAK) ? 0 : sim_tt_inpcvt(ch, TT_GET_MODE(uptr->flags)); uptr->pos = uptr->pos + 1; if (RCVENABLED()) { /* receiver enabled? */ if (RCVFULL()) /* handle data overrun */ - setbit(con_status,CONS_OE); - - con_rcv = c & 0xff; /* put in receiver register */ - setbit(con_status,CONS_DR); /* notify: data received */ + setbit(con_status, CONS_OE); + + con_rcv = ch & 0xff; /* put in receiver register */ + setbit(con_status, CONS_DR); /* notify: data received */ cpu_assertInt(INT_CONR, TRUE); /* generate interrupt because of DRQI */ if (isbitset(con_ctrl1, CONC1_ECHO)) { /* echo? XXX handle in telnet handler? */ /* XXX use direct send here, not sending via con_termsvc */ - if (isnetwork) - tmxr_putc_ln(&mux->ldsc, c); - else - sim_putchar_s(c); + sim_putchar_s(ch); } } return SCPE_OK; @@ -368,9 +298,6 @@ static int get_parity(int c, int even) // The logic in here uses the positive logic conventions as // described in the WD1931 data sheet, not the ones in the PDQ-3_Hardware_Users_Manual t_stat con_write(t_addr ioaddr, uint16 data) { - SERMUX * mux = &con_mux[0]; - UNIT *term = mux->term; - UNIT *poll = mux->poll; /* note usart has inverted bus, so all data is inverted */ data = (~data) & 0xff; @@ -379,9 +306,9 @@ t_stat con_write(t_addr ioaddr, uint16 data) { con_ctrl1 = data & 0xff; if (!RCVENABLED()) { /* disable receiver */ clrbit(con_status,CONS_FE|CONS_PE|CONS_OE|CONS_DR); - sim_cancel(poll); + sim_cancel(con_tti); } else { - sim_activate(poll, poll->wait); /* start poll service, will raise interrupt if buffer full */ + sim_activate(con_tti, con_tti->wait); /* start poll service, will raise interrupt if buffer full */ } if (!XMITENABLED()) { /* disable transmitter */ /* will drain current pending xmit service. RTS output is assumed to become inactive @@ -390,7 +317,7 @@ t_stat con_write(t_addr ioaddr, uint16 data) { if (XMITEMPTY()) { } else { /* some char in THR, start service to emit */ - sim_activate(term, term->wait); + sim_activate(con_tto, con_tto->wait); } } break; @@ -411,10 +338,10 @@ t_stat con_write(t_addr ioaddr, uint16 data) { case CONC2_CLEN8: data &= 0xff; break; } con_xmit = data & 0xff; - term->buf = data; + con_tto->buf = data; clrbit(con_status,CONS_THRE); if (XMITENABLED()) - sim_activate(term,term->wait); + sim_activate(con_tto, con_tto->wait); } // RCVINTR(); XMITINTR(); @@ -425,8 +352,6 @@ t_stat con_write(t_addr ioaddr, uint16 data) { } t_stat con_read(t_addr ioaddr, uint16 *data) { - SERMUX *mux = &con_mux[0]; - switch (ioaddr & 0x0003) { case 0: /* CTRL1 */ *data = con_ctrl1; @@ -435,8 +360,9 @@ t_stat con_read(t_addr ioaddr, uint16 *data) { *data = con_ctrl2; break; case 2: - if (mux->ldsc.conn) setbit(con_status, CONS_DSR); - else clrbit(con_status, CONS_DSR); + /* XXX find out whether terminal is attached to console? */ + setbit(con_status, CONS_DSR); +// else clrbit(con_status, CONS_DSR); *data = con_status; clrbit(con_status,CONS_DSC); /* acknowledge change in DSR/DCD */ break; @@ -569,19 +495,19 @@ t_stat tim_write(t_addr ioaddr, uint16 data) sim_debug(DBG_TIM_WRITE, &tim_dev, DBG_PCFORMAT0 "Timer%d: mode=%d\n", DBG_PC, n, (data >> 1) & 7); if (n == 3) { - printf("Unimplemented: Mode=0xc0\n"); + sim_printf("Unimplemented: Mode=0xc0\n"); return STOP_IMPL; } if (data & 0x01) { - printf("Unimplemented: BCD mode: timer=%d\n",n); + sim_printf("Unimplemented: BCD mode: timer=%d\n",n); return STOP_IMPL; } if (!( (data & 0x0e)==0x00 || (data & 0x0e)==0x04)) { - printf("Unimplemented: Mode not 0 or 2: timer=%d\n",n); + sim_printf("Unimplemented: Mode not 0 or 2: timer=%d\n",n); return STOP_IMPL; } if ((data & 0x30) != 0x30) { - printf("Unimplemented: not 16 bit load: timer=%d\n",n); + sim_printf("Unimplemented: not 16 bit load: timer=%d\n",n); return STOP_IMPL; } tim[n].mode = data; diff --git a/PDQ-3/pdq3_sys.c b/PDQ-3/pdq3_sys.c index 007d0a11..a7aca9df 100644 --- a/PDQ-3/pdq3_sys.c +++ b/PDQ-3/pdq3_sys.c @@ -191,12 +191,12 @@ static t_stat pdq3_cmd_exstack(int32 arg, char *buf) int i; int n = buf[0] ? atol(buf) : 0; if (n < 0) n = 0; - printf("SP: $%04x LOW: $%04x UPR: $%04x\n", + sim_printf("SP: $%04x LOW: $%04x UPR: $%04x\n", reg_sp, reg_splow, reg_spupr); for (i=n; i>=0; i--) { if ((rc=Read(reg_sp+i, 0, &data, 0)) != SCPE_OK) continue; - if (i==0) printf(" TOS: "); else printf(" %3d: ",i); - printf("%04x ($%04x)\n", data, reg_sp+i); + if (i==0) sim_printf(" TOS: "); else sim_printf(" %3d: ",i); + sim_printf("%04x ($%04x)\n", data, reg_sp+i); } return SCPE_OK; } diff --git a/PDQ-3/run.cmd b/PDQ-3/run.cmd index 63886fe4..54b19cb0 100644 --- a/PDQ-3/run.cmd +++ b/PDQ-3/run.cmd @@ -1,2 +1,11 @@ @echo off -pdq3.exe testhdt.sim +if not exist "..\BIN\NT\Win32-Debug\pdq3.exe" goto try_mingw +..\BIN\NT\Win32-Debug\pdq3.exe testhdt.sim +goto done + +:try_mingw +.\PDQ3.exe testhdt.sim +goto done + + +:done diff --git a/PDQ-3/testhdt.sim b/PDQ-3/testhdt.sim index 9748c7ac..c119529c 100644 --- a/PDQ-3/testhdt.sim +++ b/PDQ-3/testhdt.sim @@ -1,5 +1,9 @@ +;**** some possible debugging options ;set debug debug.log -set debug stdout +;set debug stdout + +;**** debugging of FDC +;**** read/write operations, attach&detach, FDC service, IMD handling, DMA/verbose, FDC cmds ;set fdc debug=read ;set fdc debug=write ;set fdc debug=verbose @@ -8,6 +12,9 @@ set debug stdout ;set fdc debug=dma ;set fdc debug=dmavb ;set fdc debug=cmd + +;**** debugging of CPU: exceptions, tracing, memory read/write +;**** opcode fetch, stack push/pull, concurrency ;set cpu exc ;set cpu debug=int ;set cpu debug=trace @@ -16,19 +23,37 @@ set debug stdout ;set cpu debug=fetch ;set cpu debug=stack ;set cpu debug=conc -;set con debug=svc + +;**** debugging of console: read/write to registers ;set con debug=read ;set con debug=write + +;**** debugging of timer: read/write, service ;set tim debug=read ;set tim debug=write ;set tim debug=svc -att con 8000 +;**** you should attach a telnet terminal emulator to PDQ-3 console +;**** to avoid mess with SIMH's control panel +set console telnet=8000 +;**** you might remote control SIMH's control panel +;set remote telnet=7000,telnet=buffered + +;**** you need a boot disk att fdc0 master.imd + +;**** make this write protected currently while emulator is still being debugged set fdc0 wrtlck + +;**** disable the second FDC set fdc1 disable +;************************************************************************ +;**** The following is pure f***ing magic - you must have the source code +;**** and a commented object dump of boot loader, SYSTEM.PASCAL, SYSTEM.DRIVERS etc. +; otherwise you won't understand where I had checkpoints for debugging. + ; HDT boot ;break f418:368 ;break f418:36a @@ -112,14 +137,22 @@ set fdc1 disable ;break d488:ed0 +;**** +;**** end of PFM section +;************************************************************************ - +;**** load the boot PROM code for HD support load hdt/CPU_C5.BIN +; +;**** set the INIT bit of SSR dep _ssr 80 dep _ses 80 - +;**** load some symbolic names for debuging (not needed in production) do names.sim -boot cpu -set debug stdout +;**** run +boot cpu + +;**** reset debug mode to normal when boot fails. +set debug stdout