diff --git a/HP2100/hp2100_baci.c b/HP2100/hp2100_baci.c index 8f66cb90..98079294 100644 --- a/HP2100/hp2100_baci.c +++ b/HP2100/hp2100_baci.c @@ -25,6 +25,7 @@ BACI 12966A BACI card + 02-Aug-16 JDB "baci_poll_svc" now calls "tmxr_poll_conn" unilaterally 13-May-16 JDB Modified for revised SCP API function parameter types 24-Dec-14 JDB Added casts for explicit downward conversions 10-Jan-13 MP Added DEV_MUX and additional DEVICE field values @@ -994,22 +995,24 @@ return status; scheduled. It starts when the socket is attached and stops when the socket is detached. - As there is only one line, we only poll for a new connection when the line is - disconnected. + + Implementation notes: + + 1. Even though there is only one line, we poll for new connections + unconditionally. This is so that "tmxr_poll_conn" will report "All + connections busy" to a second Telnet connection. Otherwise, the user's + client would connect but then would be silently unresponsive. */ t_stat baci_poll_svc (UNIT *uptr) { -if (baci_term.flags & UNIT_ATT) { /* attached to line? */ - if ((baci_ldsc.conn == 0) && /* line not connected? */ - (tmxr_poll_conn (&baci_desc) >= 0)) /* and new connection established? */ - baci_ldsc.rcve = 1; /* enable line to receive */ +if (tmxr_poll_conn (&baci_desc) >= 0) /* if new connection is established */ + baci_ldsc.rcve = 1; /* then enable line to receive */ - tmxr_poll_rx (&baci_desc); /* poll for input */ +tmxr_poll_rx (&baci_desc); /* poll for input */ - if (tmxr_rqln (&baci_ldsc)) /* chars available? */ - sim_activate (&baci_term, baci_term.wait); /* activate I/O service */ - } +if (tmxr_rqln (&baci_ldsc)) /* chars available? */ + sim_activate (&baci_term, baci_term.wait); /* activate I/O service */ if (uptr->wait == POLL_FIRST) /* first poll? */ uptr->wait = sync_poll (INITIAL); /* initial synchronization */ @@ -1063,18 +1066,20 @@ if (status == SCPE_OK) { return status; } + /* Detach controller */ t_stat baci_detach (UNIT *uptr) { t_stat status; -status = tmxr_detach (&baci_desc, uptr); /* detach socket */ baci_ldsc.rcve = 0; /* disable line reception */ sim_cancel (&baci_poll); /* stop Telnet poll */ +status = tmxr_detach (&baci_desc, uptr); /* detach socket */ return status; } + /* Local routines */ diff --git a/HP2100/hp2100_bugfixes.txt b/HP2100/hp2100_bugfixes.txt index 9978bf22..b2524f30 100644 --- a/HP2100/hp2100_bugfixes.txt +++ b/HP2100/hp2100_bugfixes.txt @@ -1,6 +1,6 @@ - HP 2100 SIMULATOR BUG FIX WRITEUPS - ================================== - Last update: 2016-07-28 + HP 2100 SIMULATOR FIXES + ======================= + Last update: 2016-08-05 1. PROBLEM: Booting from magnetic tape reports "HALT instruction, P: 77756 @@ -7007,7 +7007,7 @@ characters received. As the read buffers are 254 bytes long, the current count will never exceed 254. Therefore, any read terminating on a count greater than that will never complete. - + RESOLUTION: Define a new "mpx_termcnt" array to hold the termination counts for the eight lines, and reassign the "mpx_charcnt" array to hold the current character counts. Modify "exec_command" and "mpx_line_svc" @@ -7016,3 +7016,103 @@ enabled and the values are equal. STATUS: Fixed in version 4.0-0. + + + +273. ENHANCEMENT: Burst-fill only the first of two MPX receive buffers in + FASTTIME mode. + + VERSION: 4.0-0. + + OBSERVATION: When the 8-channel multiplexer is set for "optimized timing" + mode, buffered characters are transferred in blocks to and from the Telnet + connection. That is, the line service routine will send or receive + characters as long as they are available. This is more efficient than the + "realistic timing" mode, which sends or receives one character per service + invocation. Effectively, this means that up to 508 characters (two buffers + of 254 bytes each) may be sent or received between one CPU instruction or + DCPC cycle and the next. This works well for sending, but it can cause + buffer overflows when receiving. + + Consider an application (such as Kermit) that receives large blocks of data + at high speed from a client. The multiplexer is designed to handle this + condition by interrupting the CPU when the first buffer is filled and + filling the second buffer while the CPU is unloading data from the first. + In realistic mode at 19,200 baud, the CPU has approximately 800 + instructions or DCPC cycles available per character received. With a + second buffer of 254 bytes, the CPU has approximately 203,000 instructions + available to unload the first buffer after receiving the interrupt + notification. Once started, the DCPC transfer takes no more than 508 + instruction times, so the CPU can easily keep up with data arriving at the + maximum baud rate. + + In fast timing mode, however, the first buffer burst-fills in a single CPU + instruction time, and, if available from the Telnet connection, the second + buffer fills in the next instruction time. At that point, any additional + characters received will result in a buffer overflow condition. The + problem is that the CPU has no time between the first burst and the second + to empty the first buffer. + + RESOLUTION: Modify "mpx_line_svc" (hp2100_mpx.c) to shift from burst + transfers to character-at-a-time transfers when a receive buffer is full + and awaiting unloading by the CPU. This allows the CPU and DCPC time to + read the buffer contents into memory before the second multiplexer buffer + is full. Once the completed buffer is freed, the service routine returns + to burst mode to fill the remainder of the other buffer, permitting the + efficiency of block transfers while avoiding buffer overruns with large + data transfers. + + STATUS: Fixed in version 4.0-0. + + + +274. PROBLEM: A second connection to the BACI device leaves the client + unresponsive. + + VERSION: 4.0-0. + + OBSERVATION: The BACI device supports a single terminal client connection. + If a second connection is attempted, the client connects but is otherwise + unresponsive. It would be better if the client received the "All + connections busy" message that is reported by the terminal multiplexers + (MPX and MUX devices) when the number of connections is exceeded. + + CAUSE: The "baci_poll_svc" is calling the "tmxr_poll_conn" routine only if + the port is not connected. The routine should be called unilaterally, so + that it will report an error and disconnect the client when all lines are + in use and another connection is attempted. + + RESOLUTION: Modify "baci_poll_svc" (hp2100_baci.c) to call + "tmxr_poll_conn" unilaterally, so that a second concurrent connection + attempt will be rejected with "All connections busy". + + STATUS: Fixed in version 4.0-0. + + + +275. PROBLEM: The exported program counter name (PC) clashes with other libraries. + + VERSION: 4.0-0. + + OBSERVATION: In HP 21xx/1000 systems, the P register is the program + counter. In keeping with the naming of the other register variables (e.g., + for A register, B register, etc.) in the simulator, the variable used + should be named "PR". However, for traditional reasons, the program + counter in SIMH is named "PC". + + The main CPU module declares its hardware register variables as global, so + that they may be accessed by other CPU helper modules. Unfortunately, the + "curses" library also declares the symbol "PC" as global, leading to + conflicts when it is loaded by SCP. A workaround had been implemented that + renamed "PC" to "PC_Global" in the HP2100 simulator, but that meant that + the new name had to be used when debugging, which was awkward. + + CAUSE: A poor choice of global symbol names from the "termcap" library, + which was inherited by the "curses" library. + + RESOLUTION: Change the program counter variable name from "PC" to "PR" + (hp2100_cpu.c, hp2100_cpu1.c, hp2100_cpu2.c, hp2100_cpu3.c, hp2100_cpu4.c, + hp2100_cpu5.c, hp2100_cpu6.c, hp2100_cpu7.c, hp2100_dr.c, and hp2100_ipl.c) + to avoid a name clash and for register naming consistency. + + STATUS: Fixed in version 4.0-0. diff --git a/HP2100/hp2100_cpu.c b/HP2100/hp2100_cpu.c index dfe5b7ca..862a29be 100644 --- a/HP2100/hp2100_cpu.c +++ b/HP2100/hp2100_cpu.c @@ -29,6 +29,7 @@ DMA1,DMA2 12607B/12578A/12895A direct memory access controller DCPC1,DCPC2 12897B dual channel port controller + 05-Aug-16 JDB Renamed the P register from "PC" to "PR" 13-May-16 JDB Modified for revised SCP API function parameter types 31-Dec-14 JDB Corrected devdisp data parameters 30-Dec-14 JDB Added S-register parameters to ibl_copy @@ -183,7 +184,7 @@ AR<15:0> A register - addressable as location 0 BR<15:0> B register - addressable as location 1 - PC<14:0> P register - program counter + PR<14:0> P register - program counter SR<15:0> S register - switch register MR<14:0> M register - memory address TR<15:0> T register - memory data @@ -234,9 +235,9 @@ <15,10> mode action 0,0 page zero direct MA = IR<9:0> - 0,1 current page direct MA = PC<14:0>'IR,9:0> + 0,1 current page direct MA = PR<14:0>'IR,9:0> 1,0 page zero indirect MA = M[IR<9:0>] - 1,1 current page indirect MA = M[PC<14:10>'IR<9:0>] + 1,1 current page indirect MA = M[PR<14:10>'IR<9:0>] Memory reference instructions can access an address space of 32K words. An instruction can directly reference the first 1024 words of memory @@ -517,7 +518,7 @@ static uint32 fwanxm = 0; /* first word addr of nx uint16 *M = NULL; /* memory */ uint16 ABREG[2]; /* A/B registers */ -uint32 PC = 0; /* P register */ +uint32 PR = 0; /* P register */ uint32 SR = 0; /* S register */ uint32 MR = 0; /* M register */ uint32 TR = 0; /* T register */ @@ -681,7 +682,7 @@ DIB cpu_dib = { &cpuio, CPU }; UNIT cpu_unit = { UDATA (NULL, UNIT_FIX + UNIT_BINK, 0) }; REG cpu_reg[] = { - { ORDATA (P, PC, 15) }, + { ORDATA (P, PR, 15) }, { ORDATA (A, AR, 16), REG_FIT }, { ORDATA (B, BR, 16), REG_FIT }, { ORDATA (M, MR, 15) }, @@ -1015,7 +1016,7 @@ DIB *dtab [64] = { &cpu_dib, &ovfl_dib }; /* init with immutable d This routine is the instruction decode routine for the HP 2100. It is called from the simulator control program to execute instructions in simulated - memory, starting at the simulated PC. It runs until 'reason' is set to a + memory, starting at the simulated PR. It runs until 'reason' is set to a status other than SCPE_OK. */ @@ -1034,7 +1035,7 @@ int abortval; if (dev_conflict ()) /* check device assignment consistency */ return SCPE_STOP; /* conflict; stop execution */ -err_PC = PC = PC & VAMASK; /* load local PC */ +err_PC = PR = PR & VAMASK; /* load local P register */ /* Restore I/O state */ @@ -1127,7 +1128,7 @@ intrq = calc_int (); /* initial recalc of int while (reason == SCPE_OK) { /* loop until halted */ uint32 IR, MA, absel, v1, t, skip; - err_PC = PC; /* save PC for error recovery */ + err_PC = PR; /* save P for error recovery */ if (sim_interval <= 0) { /* event timeout? */ reason = sim_process_event (); /* process event service */ @@ -1284,7 +1285,7 @@ while (reason == SCPE_OK) { /* loop until halted */ iotrap = 0; /* not a trap cell instruction */ if (sim_brk_summ && /* any breakpoints? */ - sim_brk_test (PC, SWMASK ('E') | /* unconditional or */ + sim_brk_test (PR, SWMASK ('E') | /* unconditional or */ (dms_enb ? /* correct type for DMS state? */ (dms_ump ? SWMASK ('U') : SWMASK ('S')) : @@ -1294,10 +1295,10 @@ while (reason == SCPE_OK) { /* loop until halted */ } if (mp_evrff) /* violation register enabled */ - mp_viol = PC; /* update with current PC */ + mp_viol = PR; /* update with current P */ - IR = ReadW (PC); /* fetch instr */ - PC = (PC + 1) & VAMASK; + IR = ReadW (PR); /* fetch instr */ + PR = (PR + 1) & VAMASK; ion_defer = FALSE; } @@ -1359,9 +1360,9 @@ while (reason == SCPE_OK) { /* loop until halted */ mp_dms_jmp (MA, jsb_plb); /* validate jump address */ - WriteW (MA, PC); /* store PC */ + WriteW (MA, PR); /* store P */ PCQ_ENTRY; - PC = (MA + 1) & VAMASK; /* jump */ + PR = (MA + 1) & VAMASK; /* jump */ break; case 0040:case 0041:case 0042:case 0043: @@ -1433,7 +1434,7 @@ while (reason == SCPE_OK) { /* loop until halted */ mp_dms_jmp (MA, 0); /* validate jump addr */ PCQ_ENTRY; - PC = MA; /* jump */ + PR = MA; /* jump */ /* Idle conditions by operating system: @@ -1458,14 +1459,14 @@ while (reason == SCPE_OK) { /* loop until halted */ */ if ((sim_idle_enab) && (intrq == 0)) /* idle enabled w/o pending irq? */ - if (((PC == err_PC) || /* RTE through RTE-IVB */ - ((PC == (err_PC - 1)) && /* RTE-6/VM */ - ((ReadW (PC) & I_MRG) == I_ISZ))) && /* RTE jump target */ + if (((PR == err_PC) || /* RTE through RTE-IVB */ + ((PR == (err_PC - 1)) && /* RTE-6/VM */ + ((ReadW (PR) & I_MRG) == I_ISZ))) && /* RTE jump target */ (mp_fence == CLEAR) && (M [xeqt] == 0) && /* RTE idle indications */ (M [tbg] == clk_dib.select_code) || /* RTE verification */ - (PC == (err_PC - 3)) && /* DOS through DOS-III */ - (ReadW (PC) == I_STF) && /* DOS jump target */ + (PR == (err_PC - 3)) && /* DOS through DOS-III */ + (ReadW (PR) == I_STF) && /* DOS jump target */ (AR == 0177777) && (BR == 0177777) && /* DOS idle indication */ (M [m64] == 0177700) && /* DOS verification */ (M [p64] == 0000100)) /* DOS verification */ @@ -1498,7 +1499,7 @@ while (reason == SCPE_OK) { /* loop until halted */ WriteW (MA, t); if (t == 0) - PC = (PC + 1) & VAMASK; + PR = (PR + 1) & VAMASK; break; case 0100:case 0101:case 0102:case 0103: @@ -1553,7 +1554,7 @@ while (reason == SCPE_OK) { /* loop until halted */ break; /* stop execution */ if (AR != ReadW (MA)) - PC = (PC + 1) & VAMASK; + PR = (PR + 1) & VAMASK; break; case 0130:case 0131:case 0132:case 0133: @@ -1566,7 +1567,7 @@ while (reason == SCPE_OK) { /* loop until halted */ break; /* stop execution */ if (BR != ReadW (MA)) - PC = (PC + 1) & VAMASK; + PR = (PR + 1) & VAMASK; break; case 0140:case 0141:case 0142:case 0143: @@ -1702,7 +1703,7 @@ while (reason == SCPE_OK) { /* loop until halted */ } /* end if ~RSS */ ABREG[absel] = (uint16) t; /* store result */ - PC = (PC + skip) & VAMASK; /* add in skip */ + PR = (PR + skip) & VAMASK; /* add in skip */ break; /* end if alter/skip */ /* Shift instructions */ @@ -1715,7 +1716,7 @@ while (reason == SCPE_OK) { /* loop until halted */ E = 0; if ((IR & 000010) && ((t & 1) == 0)) /* SLx */ - PC = (PC + 1) & VAMASK; + PR = (PR + 1) & VAMASK; ABREG[absel] = (uint16) shift (t, IR & 00020, IR); /* do second shift */ break; /* end if shift */ @@ -1756,7 +1757,7 @@ while (reason == SCPE_OK) { /* loop until halted */ } else if (reason == NOTE_INDINT) { /* intr pend during indir? */ - PC = err_PC; /* back out of inst */ + PR = err_PC; /* back out of inst */ reason = SCPE_OK; /* continue */ } } /* end while */ @@ -1766,7 +1767,7 @@ while (reason == SCPE_OK) { /* loop until halted */ if (iotrap && (reason == STOP_HALT)) /* HLT in trap cell? */ MR = intaddr; /* M = interrupt address */ else /* normal HLT */ - MR = (PC - 1) & VAMASK; /* M = P - 1 */ + MR = (PR - 1) & VAMASK; /* M = P - 1 */ TR = ReadTAB (MR); /* T = last word fetched */ saved_MR = MR; /* save for T cmd update */ @@ -1774,7 +1775,7 @@ saved_MR = MR; /* save for T cmd update if (reason == STOP_HALT) /* programmed halt? */ cpu_set_ldr (NULL, FALSE, NULL, NULL); /* disable loader (after T is read) */ else /* simulation stop */ - PC = err_PC; /* back out instruction */ + PR = err_PC; /* back out instruction */ dms_upd_sr (); /* update dms_sr */ dms_upd_vr (MR); /* update dms_vr */ @@ -1841,7 +1842,7 @@ uint32 MA; MA = IR & (I_IA | I_DISP); /* ind + disp */ if (IR & I_CP) /* current page? */ - MA = ((PC - 1) & I_PAGENO) | MA; /* merge in page from PC */ + MA = ((PR - 1) & I_PAGENO) | MA; /* merge in page from P */ return resolve (MA, addr, irq); /* resolve indirects */ } @@ -1982,7 +1983,7 @@ iodata = IODATA (ioreturn); /* extract return data v if (((sop == soSFC) || (sop == soSFS)) && /* testing flag state? */ ((IOSIGNAL) iodata == ioSKF)) /* and SKF asserted? */ - PC = (PC + 1) & VAMASK; /* bump P to skip next instruction */ + PR = (PR + 1) & VAMASK; /* bump P to skip next instruction */ else if (sop == soLIX) /* LIA/B instruction? */ ABREG [ab] = iodata; /* load returned data */ @@ -2047,7 +2048,7 @@ t_bool calc_defer (void) uint16 IR; if (UNIT_CPU_FAMILY == UNIT_FAMILY_21XX) { /* 21xx series? */ - IR = ReadW (PC); /* prefetch next instr */ + IR = ReadW (PR); /* prefetch next instr */ if (((IR & I_MRG & ~I_AB) != 0000000) && /* is MRG instruction? */ ((IR & I_MRG_I) != I_JSB_I) && /* but not JSB,I? */ @@ -2760,12 +2761,12 @@ while (working_set) { if (UNIT_CPU_FAMILY == UNIT_FAMILY_1000) { /* 1000 series? */ memset (M, 0, (uint32) MEMSIZE * 2); /* zero allocated memory */ MR = 0077777; /* set M register */ - PC = 0100000; /* set P register */ + PR = 0100000; /* set P register */ } else { /* 21xx series */ MR = 0; /* clear M register */ - PC = 0; /* clear P register */ + PR = 0; /* clear P register */ } break; @@ -3987,7 +3988,7 @@ return SCPE_OK; /* IBL boot ROM copy - - Use memory size to set the initial PC and base of the boot area + - Use memory size to set the initial P and base of the boot area - Copy boot ROM to memory, updating I/O instructions - Place 2s complement of boot base in last location - Modify S register as indicated @@ -4007,7 +4008,7 @@ cpu_set_ldr (NULL, TRUE, NULL, NULL); /* enable loader (ignore if (dev < 010) /* valid device? */ return SCPE_ARG; -PC = ((MEMSIZE - 1) & ~IBL_MASK) & VAMASK; /* start at mem top */ +PR = ((MEMSIZE - 1) & ~IBL_MASK) & VAMASK; /* start at mem top */ for (i = 0; i < IBL_LNT; i++) { /* copy bootstrap */ wd = rom[i]; /* get word */ @@ -4015,14 +4016,14 @@ for (i = 0; i < IBL_LNT; i++) { /* copy bootstrap */ if (((wd & I_NMRMASK) == I_IO) && /* IO instruction? */ ((wd & I_DEVMASK) >= 010) && /* dev >= 10? */ (I_GETIOOP (wd) != soHLT)) /* not a HALT? */ - M[PC + i] = (wd + (dev - 010)) & DMASK; /* change dev code */ + M[PR + i] = (wd + (dev - 010)) & DMASK; /* change dev code */ else /* leave unchanged */ - M[PC + i] = wd; + M[PR + i] = wd; } -M[PC + IBL_DPC] = (M[PC + IBL_DPC] + (dev - 010)) & DMASK; /* patch DMA ctrl */ -M[PC + IBL_END] = (~PC + 1) & DMASK; /* fill in start of boot */ +M[PR + IBL_DPC] = (M[PR + IBL_DPC] + (dev - 010)) & DMASK; /* patch DMA ctrl */ +M[PR + IBL_END] = (~PR + 1) & DMASK; /* fill in start of boot */ SR = (SR & sr_clear) | sr_set; /* modify the S register as indicated */ diff --git a/HP2100/hp2100_cpu.h b/HP2100/hp2100_cpu.h index 614e3273..35343f5d 100644 --- a/HP2100/hp2100_cpu.h +++ b/HP2100/hp2100_cpu.h @@ -1,6 +1,6 @@ /* hp2100_cpu.h: HP 2100 CPU definitions - Copyright (c) 2005-2014, Robert M. Supnik + Copyright (c) 2005-2016, Robert M. Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -23,6 +23,7 @@ be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization from Robert M Supnik. + 05-Aug-16 JDB Renamed the P register from "PC" to "PR" 24-Dec-14 JDB Added casts for explicit downward conversions 18-Mar-13 JDB Added declarations for the MP abort handler and CPU registers 14-Mar-13 MP Changed guard macro name to avoid reserved namespace @@ -273,7 +274,7 @@ #define BR ABREG[1] /* B = reg 1 */ extern uint16 ABREG[2]; /* A/B regs (use AR/BR) */ -extern uint32 PC; /* P register */ +extern uint32 PR; /* P register */ extern uint32 SR; /* S register */ extern uint32 MR; /* M register */ extern uint32 TR; /* T register */ diff --git a/HP2100/hp2100_cpu1.c b/HP2100/hp2100_cpu1.c index bd09d737..c112aad5 100644 --- a/HP2100/hp2100_cpu1.c +++ b/HP2100/hp2100_cpu1.c @@ -1,6 +1,6 @@ /* hp2100_cpu1.c: HP 2100/1000 EAU simulator and UIG dispatcher - Copyright (c) 2005-2014, Robert M. Supnik + Copyright (c) 2005-2016, Robert M. Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -25,6 +25,7 @@ CPU1 Extended arithmetic and optional microcode dispatchers + 05-Aug-16 JDB Renamed the P register from "PC" to "PR" 24-Dec-14 JDB Added casts for explicit downward conversions 05-Apr-14 JDB Corrected typo in comments for cpu_ops 09-May-12 JDB Separated assignments from conditional expressions @@ -236,7 +237,7 @@ switch ((IR >> 8) & 0377) { /* decode IR<15:8> */ if (UNIT_CPU_MODEL == UNIT_1000_M) /* 1000 M-series? */ goto MPY; /* decode as MPY */ BR = (BR + 1) & DMASK; /* increment B */ - if (BR) PC = err_PC; /* if !=0, repeat */ + if (BR) PR = err_PC; /* if !=0, repeat */ break; case 004: /* RRL 100100-100117 */ @@ -742,7 +743,7 @@ for (i = 0; i < OP_N_F; i++) { flags = pattern & OP_M_FLAGS; /* get operand pattern */ if (flags >= OP_ADR) { /* address operand? */ - reason = resolve (ReadW (PC), &MA, irq); /* resolve indirects */ + reason = resolve (ReadW (PR), &MA, irq); /* resolve indirects */ if (reason != SCPE_OK) /* resolution failed? */ return reason; } @@ -765,11 +766,11 @@ for (i = 0; i < OP_N_F; i++) { break; case OP_CON: /* inline constant operand */ - *op++ = ReadOp (PC, in_s); /* get value */ + *op++ = ReadOp (PR, in_s); /* get value */ break; case OP_VAR: /* inline variable operand */ - (*op++).word = (uint16) PC; /* get pointer to variable */ + (*op++).word = (uint16) PR; /* get pointer to variable */ break; case OP_ADR: /* inline address operand */ @@ -805,7 +806,7 @@ for (i = 0; i < OP_N_F; i++) { } if (flags >= OP_CON) /* operand after instruction? */ - PC = (PC + 1) & VAMASK; /* yes, so bump to next */ + PR = (PR + 1) & VAMASK; /* yes, so bump to next */ pattern = pattern >> OP_N_FLAGS; /* move next pattern into place */ } return reason; @@ -896,7 +897,7 @@ void fprint_regs (char *caption, uint32 regs, uint32 base) static uint32 ARX, BRX, PRL; /* static so addresses are constant */ static const char *reg_names[] = { "CIR", "A", "B", "E", "X", "Y", "O", "P", "return" }; -static const uint32 *reg_ptrs[] = { &intaddr, &ARX, &BRX, &E, &XR, &YR, &O, &PC, &PRL }; +static const uint32 *reg_ptrs[] = { &intaddr, &ARX, &BRX, &E, &XR, &YR, &O, &PR, &PRL }; static const char *formats[] = { "%02o", "%06o", "%06o", "%01o", "%06o", "%06o", "%01o", "%06o", "P+%d" }; static char format[20] = " %s = "; /* base format string */ @@ -907,7 +908,7 @@ t_bool first = TRUE; /* first-time through fl ARX = AR; /* copy 16-bit value to static variable */ BRX = BR; /* copy 16-bit value to static variable */ -PRL = PC - base; /* compute value in static variable */ +PRL = PR - base; /* compute value in static variable */ for (i = 0; i < REG_COUNT; i++) { if (regs & 1) { /* register requested? */ diff --git a/HP2100/hp2100_cpu2.c b/HP2100/hp2100_cpu2.c index 716acc93..12f4ab25 100644 --- a/HP2100/hp2100_cpu2.c +++ b/HP2100/hp2100_cpu2.c @@ -1,6 +1,6 @@ /* hp2100_cpu2.c: HP 2100/1000 FP/DMS/EIG/IOP instructions - Copyright (c) 2005-2014, Robert M. Supnik + Copyright (c) 2005-2016, Robert M. Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -26,6 +26,7 @@ CPU2 Floating-point, dynamic mapping, extended, and I/O processor instructions + 05-Aug-16 JDB Renamed the P register from "PC" to "PR" 24-Dec-14 JDB Added casts for explicit downward conversions 09-May-12 JDB Separated assignments from conditional expressions 11-Sep-08 JDB Moved microcode function prototypes to hp2100_cpu1.h @@ -277,7 +278,7 @@ switch (entry) { /* decode IR<3:0> */ BR = (BR + 1) & DMASK; XR = (XR - 1) & DMASK; if (XR && intrq && !(AR & 1)) { /* more, int, even? */ - PC = err_PC; /* stop for now */ + PR = err_PC; /* stop for now */ break; } } @@ -293,7 +294,7 @@ switch (entry) { /* decode IR<3:0> */ BR = (BR + 1) & DMASK; XR = (XR - 1) & DMASK; if (XR && intrq && !(AR & 1)) { /* more, int, even? */ - PC = err_PC; /* stop for now */ + PR = err_PC; /* stop for now */ break; } } @@ -309,7 +310,7 @@ switch (entry) { /* decode IR<3:0> */ BR = (BR + 1) & DMASK; XR = (XR - 1) & DMASK; if (XR && intrq && !(AR & 1)) { /* more, int, even? */ - PC = err_PC; /* stop for now */ + PR = err_PC; /* stop for now */ break; } } @@ -323,7 +324,7 @@ switch (entry) { /* decode IR<3:0> */ BR = (BR + 1) & DMASK; XR = (XR - 1) & DMASK; if (XR && intrq) { /* more and intr? */ - PC = err_PC; /* stop for now */ + PR = err_PC; /* stop for now */ break; } } @@ -337,7 +338,7 @@ switch (entry) { /* decode IR<3:0> */ BR = (BR + 1) & DMASK; XR = (XR - 1) & DMASK; if (XR && intrq) { /* more and intr? */ - PC = err_PC; /* stop for now */ + PR = err_PC; /* stop for now */ break; } } @@ -351,7 +352,7 @@ switch (entry) { /* decode IR<3:0> */ BR = (BR + 1) & DMASK; XR = (XR - 1) & DMASK; if (XR && intrq) { /* more and intr? */ - PC = err_PC; /* stop for now */ + PR = err_PC; /* stop for now */ break; } } @@ -391,8 +392,8 @@ switch (entry) { /* decode IR<3:0> */ if (op[0].word & 0040000) dms_ump = UMAP; /* set/clr usr */ } mp_dms_jmp (op[1].word, 2); /* mpck jmp target */ - PCQ_ENTRY; /* save old PC */ - PC = op[1].word; /* jump */ + PCQ_ENTRY; /* save old P */ + PR = op[1].word; /* jump */ ion_defer = 1; /* defer intr */ break; @@ -416,7 +417,7 @@ switch (entry) { /* decode IR<3:0> */ AR = (AR + 1) & DMASK; BR = (BR + 1) & DMASK; if (intrq && ((XR & 017) == 017)) { /* intr, grp of 16? */ - PC = err_PC; /* stop for now */ + PR = err_PC; /* stop for now */ break; } } @@ -431,7 +432,7 @@ switch (entry) { /* decode IR<3:0> */ AR = (AR + 1) & DMASK; BR = (BR + 1) & DMASK; if (intrq && ((XR & 017) == 017)) { /* intr, grp of 16? */ - PC = err_PC; + PR = err_PC; break; } } @@ -459,7 +460,7 @@ switch (entry) { /* decode IR<3:0> */ case 026: /* XCA, XCB 10x726 (OP_A) */ if (ABREG[absel] != ReadWA (op[0].word)) /* compare alt */ - PC = (PC + 1) & VAMASK; + PR = (PR + 1) & VAMASK; break; case 027: /* LFA, LFB 10x727 (OP_N) */ @@ -481,16 +482,16 @@ switch (entry) { /* decode IR<3:0> */ dms_enb = 0; /* disable map */ dms_ump = SMAP; mp_dms_jmp (op[0].word, 2); /* validate jump addr */ - PCQ_ENTRY; /* save curr PC */ - PC = op[0].word; /* new PC */ + PCQ_ENTRY; /* save curr P */ + PR = op[0].word; /* new P */ ion_defer = 1; break; case 033: /* DJS 105733 (OP_A) */ if (dms_ump) dms_viol (err_PC, MVI_PRV); /* priv viol if prot */ - WriteW (op[0].word, PC); /* store ret addr */ - PCQ_ENTRY; /* save curr PC */ - PC = (op[0].word + 1) & VAMASK; /* new PC */ + WriteW (op[0].word, PR); /* store ret addr */ + PCQ_ENTRY; /* save curr P */ + PR = (op[0].word + 1) & VAMASK; /* new P */ dms_enb = 0; /* disable map */ dms_ump = SMAP; ion_defer = 1; /* defer intr */ @@ -501,16 +502,16 @@ switch (entry) { /* decode IR<3:0> */ dms_enb = 1; /* enable system */ dms_ump = SMAP; mp_dms_jmp (op[0].word, 2); /* validate jump addr */ - PCQ_ENTRY; /* save curr PC */ - PC = op[0].word; /* jump */ + PCQ_ENTRY; /* save curr P */ + PR = op[0].word; /* jump */ ion_defer = 1; /* defer intr */ break; case 035: /* SJS 105735 (OP_A) */ if (dms_ump) dms_viol (err_PC, MVI_PRV); /* priv viol if prot */ - t = PC; /* save retn addr */ - PCQ_ENTRY; /* save curr PC */ - PC = (op[0].word + 1) & VAMASK; /* new PC */ + t = PR; /* save retn addr */ + PCQ_ENTRY; /* save curr P */ + PR = (op[0].word + 1) & VAMASK; /* new P */ dms_enb = 1; /* enable system */ dms_ump = SMAP; WriteW (op[0].word, t); /* store ret addr */ @@ -522,16 +523,16 @@ switch (entry) { /* decode IR<3:0> */ dms_enb = 1; /* enable user */ dms_ump = UMAP; mp_dms_jmp (op[0].word, 2); /* validate jump addr */ - PCQ_ENTRY; /* save curr PC */ - PC = op[0].word; /* jump */ + PCQ_ENTRY; /* save curr P */ + PR = op[0].word; /* jump */ ion_defer = 1; /* defer intr */ break; case 037: /* UJS 105737 (OP_A) */ if (dms_ump) dms_viol (err_PC, MVI_PRV); /* priv viol if prot */ - t = PC; /* save retn addr */ - PCQ_ENTRY; /* save curr PC */ - PC = (op[0].word + 1) & VAMASK; /* new PC */ + t = PR; /* save retn addr */ + PCQ_ENTRY; /* save curr P */ + PR = (op[0].word + 1) & VAMASK; /* new P */ dms_enb = 1; /* enable user */ dms_ump = UMAP; WriteW (op[0].word, t); /* store ret addr */ @@ -710,19 +711,19 @@ switch (entry) { /* decode IR<4:0> */ case 020: /* ISX 105760 (OP_N) */ XR = (XR + 1) & DMASK; /* incr XR */ - if (XR == 0) PC = (PC + 1) & VAMASK; /* skip if zero */ + if (XR == 0) PR = (PR + 1) & VAMASK; /* skip if zero */ break; case 021: /* DSX 105761 (OP_N) */ XR = (XR - 1) & DMASK; /* decr XR */ - if (XR == 0) PC = (PC + 1) & VAMASK; /* skip if zero */ + if (XR == 0) PR = (PR + 1) & VAMASK; /* skip if zero */ break; case 022: /* JLY 105762 (OP_A) */ mp_dms_jmp (op[0].word, 0); /* validate jump addr */ PCQ_ENTRY; - YR = PC; /* ret addr to YR */ - PC = op[0].word; /* jump */ + YR = PR; /* ret addr to YR */ + PR = op[0].word; /* jump */ break; case 023: /* LBT 105763 (OP_N) */ @@ -749,7 +750,7 @@ switch (entry) { /* decode IR<4:0> */ BR = (BR + 1) & DMASK; /* incr dst */ wc = (wc - 1) & DMASK; /* decr cnt */ if (intrq && wc) { /* intr, more to do? */ - PC = err_PC; /* back up PC */ + PR = err_PC; /* back up P */ break; } } @@ -764,7 +765,7 @@ switch (entry) { /* decode IR<4:0> */ v1 = ReadB (AR); /* get src1 */ v2 = ReadB (BR); /* get src2 */ if (v1 != v2) { /* compare */ - PC = (PC + 1 + (v1 > v2)) & VAMASK; + PR = (PR + 1 + (v1 > v2)) & VAMASK; BR = (BR + wc) & DMASK; /* update BR */ wc = 0; /* clr interim */ break; @@ -773,7 +774,7 @@ switch (entry) { /* decode IR<4:0> */ BR = (BR + 1) & DMASK; /* incr src2 */ wc = (wc - 1) & DMASK; /* decr cnt */ if (intrq && wc) { /* intr, more to do? */ - PC = err_PC; /* back up PC */ + PR = err_PC; /* back up P */ break; } } @@ -788,11 +789,11 @@ switch (entry) { /* decode IR<4:0> */ if (t == v1) break; /* test match? */ BR = (BR + 1) & DMASK; if (t == v2) { /* term match? */ - PC = (PC + 1) & VAMASK; + PR = (PR + 1) & VAMASK; break; } if (intrq) { /* int pending? */ - PC = err_PC; /* back up PC */ + PR = err_PC; /* back up P */ break; } } @@ -800,19 +801,19 @@ switch (entry) { /* decode IR<4:0> */ case 030: /* ISY 105770 (OP_N) */ YR = (YR + 1) & DMASK; /* incr YR */ - if (YR == 0) PC = (PC + 1) & VAMASK; /* skip if zero */ + if (YR == 0) PR = (PR + 1) & VAMASK; /* skip if zero */ break; case 031: /* DSY 105771 (OP_N) */ YR = (YR - 1) & DMASK; /* decr YR */ - if (YR == 0) PC = (PC + 1) & VAMASK; /* skip if zero */ + if (YR == 0) PR = (PR + 1) & VAMASK; /* skip if zero */ break; case 032: /* JPY 105772 (OP_C) */ op[0].word = (op[0].word + YR) & VAMASK; /* index, no indir */ mp_dms_jmp (op[0].word, 0); /* validate jump addr */ PCQ_ENTRY; - PC = op[0].word; /* jump */ + PR = op[0].word; /* jump */ break; case 033: /* SBS 105773 (OP_KA) */ @@ -827,7 +828,7 @@ switch (entry) { /* decode IR<4:0> */ case 035: /* TBS 105775 (OP_KK) */ if ((op[1].word & op[0].word) != op[0].word) /* test bits */ - PC = (PC + 1) & VAMASK; + PR = (PR + 1) & VAMASK; break; case 036: /* CMW 105776 (OP_KV) */ @@ -840,7 +841,7 @@ switch (entry) { /* decode IR<4:0> */ sop1 = (int32) SEXT (v1); /* signed */ sop2 = (int32) SEXT (v2); if (sop1 != sop2) { /* compare */ - PC = (PC + 1 + (sop1 > sop2)) & VAMASK; + PR = (PR + 1 + (sop1 > sop2)) & VAMASK; BR = (BR + wc) & DMASK; /* update BR */ wc = 0; /* clr interim */ break; @@ -849,7 +850,7 @@ switch (entry) { /* decode IR<4:0> */ BR = (BR + 1) & DMASK; /* incr src2 */ wc = (wc - 1) & DMASK; /* decr cnt */ if (intrq && wc) { /* intr, more to do? */ - PC = err_PC; /* back up PC */ + PR = err_PC; /* back up P */ break; } } @@ -870,7 +871,7 @@ switch (entry) { /* decode IR<4:0> */ BR = (BR + 1) & DMASK; /* incr dst */ wc = (wc - 1) & DMASK; /* decr cnt */ if (intrq && wc) { /* intr, more to do? */ - PC = err_PC; /* back up PC */ + PR = err_PC; /* back up P */ break; } } @@ -1044,7 +1045,7 @@ switch (entry) { /* decode IR<5:0> */ WriteW ((BR - 1) & VAMASK, 0); /* entry link */ WriteW ((tp - 1) & VAMASK, BR); /* tail link */ WriteW ((AR + 1) & VAMASK, BR); /* queue tail */ - if (hp != 0) PC = (PC + 1) & VAMASK; /* q not empty? skip */ + if (hp != 0) PR = (PR + 1) & VAMASK; /* q not empty? skip */ break; case 005: /* PENQ 105465 (OP_N) */ @@ -1053,7 +1054,7 @@ switch (entry) { /* decode IR<5:0> */ WriteW (AR & VAMASK, BR); /* queue head */ if (hp == 0) /* q empty? */ WriteW ((AR + 1) & VAMASK, BR); /* queue tail */ - else PC = (PC + 1) & VAMASK; /* skip */ + else PR = (PR + 1) & VAMASK; /* skip */ break; case 006: /* DEQ 105466 (OP_N) */ @@ -1063,7 +1064,7 @@ switch (entry) { /* decode IR<5:0> */ WriteW (AR & VAMASK, hp); /* becomes queue head */ if (hp == 0) /* q now empty? */ WriteW ((AR + 1) & VAMASK, (AR + 1) & DMASK); - PC = (PC + 1) & VAMASK; /* skip */ + PR = (PR + 1) & VAMASK; /* skip */ } break; @@ -1078,7 +1079,7 @@ switch (entry) { /* decode IR<5:0> */ wc = (wc - 1) & DMASK; /* decr cnt */ if (wc && intrq) { /* more and intr? */ WriteW (op[0].word, wc); /* save count */ - PC = err_PC; /* stop for now */ + PR = err_PC; /* stop for now */ break; } } @@ -1101,7 +1102,7 @@ switch (entry) { /* decode IR<5:0> */ case 012: /* PRFEX 105472 (OP_A) */ PCQ_ENTRY; - PC = ReadW (op[0].word) & VAMASK; /* jump indirect */ + PR = ReadW (op[0].word) & VAMASK; /* jump indirect */ WriteW (op[0].word, 0); /* clear exit */ break; diff --git a/HP2100/hp2100_cpu3.c b/HP2100/hp2100_cpu3.c index 8e48372e..928abf63 100644 --- a/HP2100/hp2100_cpu3.c +++ b/HP2100/hp2100_cpu3.c @@ -1,6 +1,6 @@ /* hp2100_cpu3.c: HP 2100/1000 FFP/DBI instructions - Copyright (c) 2005-2014, J. David Bryan + Copyright (c) 2005-2016, J. David Bryan Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -25,6 +25,7 @@ CPU3 Fast FORTRAN and Double Integer instructions + 05-Aug-16 JDB Renamed the P register from "PC" to "PR" 24-Dec-14 JDB Added casts for explicit downward conversions 09-May-12 JDB Separated assignments from conditional expressions 11-Sep-08 JDB Moved microcode function prototypes to hp2100_cpu1.h @@ -212,7 +213,7 @@ else { /* F-Series */ SR = 0102077; /* test passed code */ AR = 0; /* test clears A/B */ BR = 0; - PC = (PC + 1) & VAMASK; /* P+2 return for firmware w/DBI */ + PR = (PR + 1) & VAMASK; /* P+2 return for firmware w/DBI */ return reason; case 003: /* .DNG 105203 (OP_N) */ @@ -304,7 +305,7 @@ switch (entry) { /* decode IR<4:0> */ return stop_inst; /* trap if not */ if (intrq) { /* interrupt pending? */ - PC = err_PC; /* restart instruction */ + PR = err_PC; /* restart instruction */ break; } @@ -317,7 +318,7 @@ switch (entry) { /* decode IR<4:0> */ i = 1; /* params start at op[1] */ XADD: /* enter here from .XADD */ if (intrq) { /* interrupt pending? */ - PC = err_PC; /* restart instruction */ + PR = err_PC; /* restart instruction */ break; } @@ -329,7 +330,7 @@ switch (entry) { /* decode IR<4:0> */ i = 1; /* params start at op[1] */ XSUB: /* enter here from .XSUB */ if (intrq) { /* interrupt pending? */ - PC = err_PC; /* restart instruction */ + PR = err_PC; /* restart instruction */ break; } @@ -341,7 +342,7 @@ switch (entry) { /* decode IR<4:0> */ i = 1; /* params start at op[1] */ XMPY: /* enter here from .XMPY */ if (intrq) { /* interrupt pending? */ - PC = err_PC; /* restart instruction */ + PR = err_PC; /* restart instruction */ break; } @@ -353,7 +354,7 @@ switch (entry) { /* decode IR<4:0> */ i = 1; /* params start at op[1] */ XDIV: /* enter here from .XDIV */ if (intrq) { /* interrupt pending? */ - PC = err_PC; /* restart instruction */ + PR = err_PC; /* restart instruction */ break; } @@ -383,7 +384,7 @@ switch (entry) { /* decode IR<4:0> */ return stop_inst; /* trap if not */ if (intrq) { /* interrupt pending? */ - PC = err_PC; /* restart instruction */ + PR = err_PC; /* restart instruction */ break; } @@ -397,7 +398,7 @@ switch (entry) { /* decode IR<4:0> */ return stop_inst; /* trap if not */ if (intrq) { /* interrupt pending? */ - PC = err_PC; /* restart instruction */ + PR = err_PC; /* restart instruction */ break; } @@ -411,7 +412,7 @@ switch (entry) { /* decode IR<4:0> */ case 020: /* .XFER 105220 (OP_N) */ if (UNIT_CPU_TYPE == UNIT_TYPE_2100) - PC = (PC + 1) & VAMASK; /* 2100 .XFER returns to P+2 */ + PR = (PR + 1) & VAMASK; /* 2100 .XFER returns to P+2 */ XFER: /* enter here from .DFER */ sc = 3; /* set count for 3-wd xfer */ goto CFER; /* do transfer */ @@ -420,20 +421,20 @@ switch (entry) { /* decode IR<4:0> */ if ((int16) op[1].word < 1) /* index < 1? */ op[1].word = 1; /* reset min */ - sa = PC + op[1].word - 1; /* point to jump target */ + sa = PR + op[1].word - 1; /* point to jump target */ if (sa >= op[0].word) /* must be <= last target */ sa = op[0].word - 1; da = ReadW (sa); /* get jump target */ reason = resolve (da, &MA, intrq); /* resolve indirects */ if (reason != SCPE_OK) { /* resolution failed? */ - PC = err_PC; /* irq restarts instruction */ + PR = err_PC; /* irq restarts instruction */ break; } mp_dms_jmp (MA, 2); /* validate jump addr */ - PCQ_ENTRY; /* record last PC */ - PC = MA; /* jump */ + PCQ_ENTRY; /* record last P */ + PR = MA; /* jump */ BR = op[0].word; /* (for 2100 FFP compat) */ break; @@ -446,7 +447,7 @@ switch (entry) { /* decode IR<4:0> */ else { /* 3-dim access */ reason = cpu_ops (OP_KK, op2, intrq); /* get 1st, 2nd ranges */ if (reason != SCPE_OK) { /* evaluation failed? */ - PC = err_PC; /* irq restarts instruction */ + PR = err_PC; /* irq restarts instruction */ break; } op[1].word = op[1].word + /* offset */ @@ -458,7 +459,7 @@ switch (entry) { /* decode IR<4:0> */ break; case 023: /* .ENTR 105223 (OP_A) */ - MA = PC - 3; /* get addr of entry point */ + MA = PR - 3; /* get addr of entry point */ ENTR: /* enter here from .ENTP */ da = op[0].word; /* get addr of 1st formal */ dc = MA - da; /* get count of formals */ @@ -473,7 +474,7 @@ switch (entry) { /* decode IR<4:0> */ MA = ReadW (sa++); /* get addr of actual */ reason = resolve (MA, &MA, intrq); /* resolve indirect */ if (reason != SCPE_OK) { /* resolution failed? */ - PC = err_PC; /* irq restarts instruction */ + PR = err_PC; /* irq restarts instruction */ break; } WriteW (da++, MA); /* put addr into formal */ @@ -484,7 +485,7 @@ switch (entry) { /* decode IR<4:0> */ break; case 024: /* .ENTP 105224 (OP_A) */ - MA = PC - 5; /* get addr of entry point */ + MA = PR - 5; /* get addr of entry point */ goto ENTR; case 025: /* .PWR2 105225 (OP_RK) */ @@ -521,7 +522,7 @@ switch (entry) { /* decode IR<4:0> */ if (op[0].word && intrq) { /* more and intr? */ AR = (uint16) sa; /* restore A */ BR = (uint16) sb; /* restore B */ - PC = err_PC; /* restart instruction */ + PR = err_PC; /* restart instruction */ break; } } @@ -666,7 +667,7 @@ switch (entry) { /* decode IR<3:0> */ XR = 2; /* set revision */ BR = 0377; /* side effect of microcode */ SR = 0102077; /* set "pass" code */ - PC = (PC + 1) & VAMASK; /* return to P+1 */ + PR = (PR + 1) & VAMASK; /* return to P+1 */ t = (AR << 16) | BR; /* set t for return */ break; @@ -746,9 +747,9 @@ switch (entry) { /* decode IR<3:0> */ case 004: /* .DCO 105324 (OP_JD) */ t = op[0].dword; /* copy for later store */ if ((int32) op[0].dword < (int32) op[1].dword) - PC = (PC + 1) & VAMASK; /* < rtns to P+2 */ + PR = (PR + 1) & VAMASK; /* < rtns to P+2 */ else if ((int32) op[0].dword > (int32) op[1].dword) - PC = (PC + 2) & VAMASK; /* > rtns to P+3 */ + PR = (PR + 2) & VAMASK; /* > rtns to P+3 */ break; /* = rtns to P+1 */ case 005: /* .DDI 105325 (OP_JD) */ @@ -796,7 +797,7 @@ switch (entry) { /* decode IR<3:0> */ t = din.dword = din.dword + 1; /* increment value */ WriteOp (op[0].word, din, in_d); /* store it back */ if (t == 0) - PC = (PC + 1) & VAMASK; /* skip if result zero */ + PR = (PR + 1) & VAMASK; /* skip if result zero */ break; case 013: /* .DDS 105333 (OP_A) */ @@ -804,7 +805,7 @@ switch (entry) { /* decode IR<3:0> */ t = din.dword = din.dword - 1; /* decrement value */ WriteOp (op[0].word, din, in_d); /* write it back */ if (t == 0) - PC = (PC + 1) & VAMASK; /* skip if result zero */ + PR = (PR + 1) & VAMASK; /* skip if result zero */ break; case 014: /* .DSBR 105334 (OP_JD) */ diff --git a/HP2100/hp2100_cpu4.c b/HP2100/hp2100_cpu4.c index 85dab53b..b7a2482a 100644 --- a/HP2100/hp2100_cpu4.c +++ b/HP2100/hp2100_cpu4.c @@ -1,6 +1,6 @@ /* hp2100_cpu4.c: HP 1000 FPP/SIS - Copyright (c) 2006-2014, J. David Bryan + Copyright (c) 2006-2016, J. David Bryan Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -25,6 +25,7 @@ CPU4 Floating Point Processor and Scientific Instruction Set + 05-Aug-16 JDB Renamed the P register from "PC" to "PR" 24-Dec-14 JDB Added casts for explicit downward conversions 09-May-12 JDB Separated assignments from conditional expressions 06-Feb-12 JDB Added OPSIZE casts to fp_accum calls in .FPWR/.TPWR @@ -302,7 +303,7 @@ switch (entry) { /* decode IR<6:0> */ case 0004: /* [tst] 105004 (OP_N) */ XR = 3; /* firmware revision */ SR = 0102077; /* test passed code */ - PC = (PC + 1) & VAMASK; /* P+2 return for firmware w/DBI */ + PR = (PR + 1) & VAMASK; /* P+2 return for firmware w/DBI */ break; case 0005: /* [xpd] 105005 (OP_C) */ @@ -313,22 +314,22 @@ switch (entry) { /* decode IR<6:0> */ case 0007: /* [stk] 105007 (OP_A) */ O = 0; /* clear overflow */ - stk_ptr = (uint16) PC; /* save ptr to next buf */ + stk_ptr = (uint16) PR; /* save ptr to next buf */ rtn_addr = op[0].word; /* save return address */ while (TRUE) { - PC = ReadW (stk_ptr) & VAMASK; /* point at next instruction set */ + PR = ReadW (stk_ptr) & VAMASK; /* point at next instruction set */ stk_ptr = (stk_ptr + 1) & VAMASK; reason = cpu_ops (OP_CCACACCA, op, intrq); /* get instruction set */ if (reason) { - PC = err_PC; /* irq restarts */ + PR = err_PC; /* irq restarts */ break; } if (op[0].word == 0) { /* opcode = NOP? */ - PC = (rtn_addr + 1) & VAMASK; /* bump to good return */ + PR = (rtn_addr + 1) & VAMASK; /* bump to good return */ break; /* done */ } @@ -336,7 +337,7 @@ switch (entry) { /* decode IR<6:0> */ &op1_prec, &op2_prec, &rslt_prec); if (TO_COUNT(op1_prec) != op[1].word) { /* first operand precisions agree? */ - PC = rtn_addr; /* no, so take error return */ + PR = rtn_addr; /* no, so take error return */ break; } @@ -344,7 +345,7 @@ switch (entry) { /* decode IR<6:0> */ op[1] = ReadOp (op[2].word, op1_prec); /* no, so get operand 1 */ if (TO_COUNT(op2_prec) != op[3].word) { /* second operand precisions agree? */ - PC = rtn_addr; /* no, so take error return */ + PR = rtn_addr; /* no, so take error return */ break; } @@ -633,7 +634,7 @@ switch (entry) { /* decode IR<3:0> */ if (multiple & 0002) /* multiple * 2 odd? */ fp_exec (0064, &op[0], minus_1, NOP); /* res = -1.0 / acc */ - PC = (PC + 1) & VAMASK; /* normal return is P+2 */ + PR = (PR + 1) & VAMASK; /* normal return is P+2 */ break; @@ -641,7 +642,7 @@ switch (entry) { /* decode IR<3:0> */ O = 0; /* clear overflow */ if (op[0].fpk[0] == 0) { /* arg = 0? */ - PC = (PC + 1) & VAMASK; /* normal return is P+2 */ + PR = (PR + 1) & VAMASK; /* normal return is P+2 */ break; } @@ -688,7 +689,7 @@ switch (entry) { /* decode IR<3:0> */ fp_pack (&op[0], op[1], exponent, fp_f);/* repack result */ } - PC = (PC + 1) & VAMASK; /* normal return is P+2 */ + PR = (PR + 1) & VAMASK; /* normal return is P+2 */ break; @@ -728,7 +729,7 @@ switch (entry) { /* decode IR<3:0> */ if (entry == 007) /* ALOGT? */ fp_exec (0050, &op[0], NOP, log_e); /* res = acc * log(e) */ - PC = (PC + 1) & VAMASK; /* normal return is P+2 */ + PR = (PR + 1) & VAMASK; /* normal return is P+2 */ break; @@ -812,7 +813,7 @@ switch (entry) { /* decode IR<3:0> */ if (multiple & 0002) /* multiple * 2 odd? */ fp_pcom (&op[0], fp_f); /* make negative */ - PC = (PC + 1) & VAMASK; /* normal return is P+2 */ + PR = (PR + 1) & VAMASK; /* normal return is P+2 */ break; @@ -833,7 +834,7 @@ switch (entry) { /* decode IR<3:0> */ op[0].fpk[0] = 0; /* result is zero */ op[0].fpk[1] = 0; O = 0; /* clear for underflow */ - PC = (PC + 1) & VAMASK; /* normal return is P+2 */ + PR = (PR + 1) & VAMASK; /* normal return is P+2 */ break; } @@ -871,7 +872,7 @@ switch (entry) { /* decode IR<3:0> */ } } - PC = (PC + 1) & VAMASK; /* normal return is P+2 */ + PR = (PR + 1) & VAMASK; /* normal return is P+2 */ break; @@ -896,7 +897,7 @@ switch (entry) { /* decode IR<3:0> */ else { /* 0.5 <= abs (arg) < 8.0 */ BR = BR + 2; /* arg = arg * 2.0 */ cpu_sis (0105326, intrq); /* calc exp (arg) */ - PC = (PC - 1) & VAMASK; /* correct P (always good rtn) */ + PR = (PR - 1) & VAMASK; /* correct P (always good rtn) */ op[0].fpk[0] = AR; /* save value */ op[0].fpk[1] = BR; @@ -995,7 +996,7 @@ switch (entry) { /* decode IR<3:0> */ if ((f < 0) || (f == 2) || (f == 6) || /* EXP, TANH, or COS? */ (exponent - rsltexp < 5)) { /* bits lost < 5? */ WriteOp (op[0].word, result, fp_t); /* write result */ - PC = (PC + 1) & VAMASK; /* P+2 return for good result */ + PR = (PR + 1) & VAMASK; /* P+2 return for good result */ op[0].fpk[1] = BR; /* return LSBs of N in B */ break; /* all done! */ } @@ -1047,7 +1048,7 @@ switch (entry) { /* decode IR<3:0> */ fp_exec (0012, &result, NOP, op[5]); /* result = acc + (x - xu) * c + (cu * xu - n) */ WriteOp (op[0].word, result, fp_t); /* write result */ - PC = (PC + 1) & VAMASK; /* P+2 return for good result */ + PR = (PR + 1) & VAMASK; /* P+2 return for good result */ op[0].fpk[1] = BR; /* return LSBs of N in B */ break; @@ -1112,7 +1113,7 @@ switch (entry) { /* decode IR<3:0> */ case 017: /* [tst] 105337 (OP_N) */ XR = 4; /* firmware revision */ SR = 0102077; /* test passed code */ - PC = (PC + 1) & VAMASK; /* P+2 return for firmware w/DPOLY */ + PR = (PR + 1) & VAMASK; /* P+2 return for firmware w/DPOLY */ return reason; diff --git a/HP2100/hp2100_cpu5.c b/HP2100/hp2100_cpu5.c index 89078acb..f88f89eb 100644 --- a/HP2100/hp2100_cpu5.c +++ b/HP2100/hp2100_cpu5.c @@ -1,7 +1,7 @@ /* hp2100_cpu5.c: HP 1000 RTE-6/VM VMA and RTE-IV EMA instructions Copyright (c) 2007-2008, Holger Veit - Copyright (c) 2006-2014, J. David Bryan + Copyright (c) 2006-2016, J. David Bryan Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -26,6 +26,7 @@ CPU5 RTE-6/VM and RTE-IV firmware option instructions + 05-Aug-16 JDB Renamed the P register from "PC" to "PR" 24-Dec-14 JDB Added casts for explicit downward conversions 17-Dec-12 JDB Fixed cpu_vma_mapte to return FALSE if not a VMA program 09-May-12 JDB Separated assignments from conditional expressions @@ -190,18 +191,18 @@ uint32 eqt,mls,pnod,lstpg,fstpg,rotsz,lgpg,relpg,relbp,matloc,ptnpg,physpg,cnt,p eqt = ReadIO(xeqt,UMAP); /* get ID segment */ mls = ReadIO(eqt+33,SMAP); /* get word33 of alternate map */ if ((mls & 0x8000) == 0) { /* this is not an MLS prog! */ - PC = err_PC; + PR = err_PC; if (debug) - fprintf(sim_deb,">>CPU VMA: cpu_vma_loc at P=%06o: not an MLS program\n", PC); + fprintf(sim_deb,">>CPU VMA: cpu_vma_loc at P=%06o: not an MLS program\n", PR); if (mp_control) MP_ABORT (eqt+33); /* allow an MP abort */ return STOP_HALT; /* FATAL error! */ } pnod = mls & 01777; /* get #pages of mem res nodes */ if (pnod == 0) { /* no pages? FATAL! */ - PC = err_PC; + PR = err_PC; if (debug) - fprintf(sim_deb,">>CPU VMA: cpu_vma_loc at P=%06o: no mem resident pages\n", PC); + fprintf(sim_deb,">>CPU VMA: cpu_vma_loc at P=%06o: no mem resident pages\n", PR); if (mp_control) MP_ABORT (eqt+33); /* allow an MP abort */ return STOP_HALT; } @@ -213,20 +214,20 @@ lgpg = op[0].word; /* lets do some consistency checks, CPU halt if they fail */ if (lstpg < lgpg || lgpg < fstpg) { /* assert LSTPG >= LGPG# >= FSTPG */ - PC = err_PC; + PR = err_PC; if (debug) fprintf(sim_deb, - ">>CPU VMA: $LOC at P=%06o: failed check LSTPG >= LGPG# >= FSTPG\n",PC); + ">>CPU VMA: $LOC at P=%06o: failed check LSTPG >= LGPG# >= FSTPG\n",PR); if (mp_control) MP_ABORT (eqt+22); /* allow an MP abort */ return STOP_HALT; } relpg = op[1].word; if (pnod < relpg || relpg < (rotsz+1)) { /* assert #PNOD >= RELPG >= ROTSZ+1 */ - PC = err_PC; + PR = err_PC; if (debug) fprintf(sim_deb, - ">>CPU VMA: $LOC at %06o: failed check #PNOD >= RELPG >= ROTSZ+1\n",PC); + ">>CPU VMA: $LOC at %06o: failed check #PNOD >= RELPG >= ROTSZ+1\n",PR); if (mp_control) MP_ABORT (eqt+22); /* allow an MP abort */ return STOP_HALT; } @@ -234,10 +235,10 @@ if (pnod < relpg || relpg < (rotsz+1)) { /* assert #PNOD >= RELPG >= relbp = op[2].word; if (relbp != 0) /* assert RELBP == 0 OR */ if (pnod < relbp || relbp < (rotsz+1)) { /* #PNOD >= RELBP >= ROTSZ+1 */ - PC = err_PC; + PR = err_PC; if (debug) fprintf(sim_deb, - ">>CPU VMA: $LOC at P=%06o: failed check: #PNOD >= RELBP >= ROTSZ+1\n",PC); + ">>CPU VMA: $LOC at P=%06o: failed check: #PNOD >= RELBP >= ROTSZ+1\n",PR); if (mp_control) MP_ABORT (eqt+22); /* allow an MP abort */ return STOP_HALT; } @@ -266,13 +267,13 @@ while (cnt != 0) { dms_wmap(32,relbp+ptnpg); /* map base page again */ WriteW(op[3].word,op[4].word); /* path# we are going to */ -PC = (PC - 8) & DMASK; /* adjust PC to return address */ +PR = (PR - 8) & DMASK; /* adjust P to return address */ /* word before the $LOC microinstr. */ -PC = (ReadW(PC) - 1) & DMASK; /* but the call has to be rerun, */ +PR = (ReadW(PR) - 1) & DMASK; /* but the call has to be rerun, */ /* so must skip back to the original call */ /* which will now lead to the real routine */ if (debug) - fprintf(sim_deb,">>CPU VMA: $LOC done: path#=%06o, P=%06o\n",op[4].word,PC); + fprintf(sim_deb,">>CPU VMA: $LOC done: path#=%06o, P=%06o\n",op[4].word,PR); return SCPE_OK; } @@ -314,7 +315,7 @@ if (ReadIO(ema+1,UMAP) != 0104400) { return STOP_HALT; /* FATAL: no EMA/VMA! */ } -PC = (ema+1) & VAMASK; /* restart $EMA$ user code, */ +PR = (ema+1) & VAMASK; /* restart $EMA$ user code, */ /* will return to fault instruction */ AR = (ptr >> 16) & DMASK; /* restore A, B */ @@ -323,7 +324,7 @@ E = 0; /* enforce E = 0 */ if (debug) fprintf(sim_deb, ">>CPU VMA: Call pg fault OS exit, AR=%06o BR=%06o P=%06o\n", - AR, BR, PC); + AR, BR, PR); return SCPE_OK; } @@ -489,7 +490,7 @@ if (mapnm > 31) { /* check for invalid map reg AR = 80; /* error: corrupt EMA/VMA system */ if (debug) fprintf(sim_deb, ">>CPU VMA: .PMAP invalid mapr: AR=80, exit P+1\n"); - return SCPE_OK; /* return exit PC+1 */ + return SCPE_OK; /* return exit P+1 */ } ptr = (umapr << 16) | (pagid & DMASK); /* build the ptr argument for vma_fault */ @@ -501,9 +502,9 @@ if (!cpu_vma_mapte(&pgpte)) { /* map the PTE */ fprintf(sim_deb, ">>CPU VMA: .PMAP pg fault&bit15: XR=%06o YR=%06o, exit P+1\n", XR, YR); - return SCPE_OK; /* use PC+1 error exit */ + return SCPE_OK; /* use P+1 error exit */ } - return cpu_vma_fault(65535,ptemiss,-1,pgpte,ptr,PC-1,debug); /* oops: fix PTE */ + return cpu_vma_fault(65535,ptemiss,-1,pgpte,ptr,PR-1,debug); /* oops: fix PTE */ } /* PTE is successfully mapped to page31 and dmsmap[63] */ @@ -515,9 +516,9 @@ if (!cpu_vma_ptevl(pagid,&physpg)) { fprintf(sim_deb, ">>CPU VMA: .PMAP pg map&bit15: XR=%06o YR=%06o, exit P+1\n", XR, YR); - return SCPE_OK; /* use PC+1 error exit*/ + return SCPE_OK; /* use P+1 error exit*/ } - return cpu_vma_fault(pagid,page31,31,pgpte,ptr,PC-1,debug); /* page not present */ + return cpu_vma_fault(pagid,page31,31,pgpte,ptr,PR-1,debug); /* page not present */ } E = 1; @@ -532,7 +533,7 @@ if (mapnm != 31) /* unless already unmapped, AR = (umapr + 1) & DMASK; /* increment mapr for next call */ BR = (pagid + 1) & DMASK; /* increment pagid for next call */ O = 0; /* clear overflow */ -PC = (PC + 1) & VAMASK; /* normal PC+2 return */ +PR = (PR + 1) & VAMASK; /* normal P+2 return */ if (debug) fprintf(sim_deb,">>CPU VMA: .PMAP map done: AR=%06o BR=%o6o exit P+2\n",AR,BR); return SCPE_OK; @@ -656,7 +657,7 @@ uint16 t16; uint32 entry,t32,ndim; uint32 dtbl,atbl; /* descriptor table ptr, actual args ptr */ OP dop0,dop1; -uint32 pcsave = (PC+1) & VAMASK; /* save PC to check for redo in imap/jmap */ +uint32 pcsave = (PR+1) & VAMASK; /* save P to check for redo in imap/jmap */ t_bool debug = DEBUG_PRI (cpu_dev, DEB_VMA); entry = IR & 017; /* mask to entry point */ @@ -693,7 +694,7 @@ switch (entry) { /* decode IR<3:0> */ XR = 3; /* refer to src code 92084-18828 rev 3 */ SR = 0102077; /* HLT 77 instruction */ YR = 1; /* ROMs correctly installed */ - PC = (PC+1) & VAMASK; /* skip instr if VMA/EMA ROM installed */ + PR = (PR+1) & VAMASK; /* skip instr if VMA/EMA ROM installed */ break; case 003: /* [swap] 105243 (OP_N) */ @@ -723,16 +724,16 @@ switch (entry) { /* decode IR<3:0> */ case 010: /* .IMAP 105250 (OP_A) */ dtbl = op[0].word; - atbl = PC; + atbl = PR; reason = cpu_vma_ijmar(in_s,dtbl,atbl,&ndim,intrq,debug); /* calc the virt address to AB */ if (reason) return reason; t32 = (AR << 16) | (BR & DMASK); - reason = cpu_vma_lbp(t32,0,PC-2,intrq,debug); + reason = cpu_vma_lbp(t32,0,PR-2,intrq,debug); if (reason) return reason; - if (PC==pcsave) - PC = (PC+ndim) & VAMASK; /* adjust PC: skip ndim subscript words */ + if (PR==pcsave) + PR = (PR+ndim) & VAMASK; /* adjust P: skip ndim subscript words */ break; case 011: /* .IMAR 105251 (OP_A) */ @@ -743,16 +744,16 @@ switch (entry) { /* decode IR<3:0> */ case 012: /* .JMAP 105252 (OP_A) */ dtbl = op[0].word; - atbl = PC; + atbl = PR; reason = cpu_vma_ijmar(in_d,dtbl,atbl,&ndim,intrq,debug); /* calc the virtual address to AB */ if (reason) return reason; t32 = (AR << 16) | (BR & DMASK); - reason = cpu_vma_lbp(t32,0,PC-2,intrq,debug); + reason = cpu_vma_lbp(t32,0,PR-2,intrq,debug); if (reason) return reason; - if (PC==pcsave) - PC = (PC + ndim) & VAMASK; /* adjust PC: skip ndim subscript dword ptr */ + if (PR==pcsave) + PR = (PR + ndim) & VAMASK; /* adjust P: skip ndim subscript dword ptr */ break; case 013: /* .JMAR 105253 (OP_A) */ @@ -765,23 +766,23 @@ switch (entry) { /* decode IR<3:0> */ dop0 = ReadOp(op[0].word,in_d); /* get pointer from arg */ dop1 = ReadOp(op[1].word,in_d); t32 = dop0.dword + dop1.dword; /* add offset to it */ - reason = cpu_vma_lbp(t32,0,PC-3,intrq,debug); + reason = cpu_vma_lbp(t32,0,PR-3,intrq,debug); break; case 015: /* .LPX 105255 (OP_A) */ t32 = (AR << 16) | (BR & DMASK); /* pointer in AB */ dop0 = ReadOp(op[0].word,in_d); - reason = cpu_vma_lbp(t32,dop0.dword,PC-2,intrq,debug); + reason = cpu_vma_lbp(t32,dop0.dword,PR-2,intrq,debug); break; case 016: /* .LBPR 105256 (OP_A) */ dop0 = ReadOp(op[0].word,in_d); /* get the pointer */ - reason = cpu_vma_lbp(dop0.dword,0,PC-2,intrq,debug); + reason = cpu_vma_lbp(dop0.dword,0,PR-2,intrq,debug); break; case 017: /* .LBP 105257 (OP_N) */ t32 = (AR << 16) | (BR & DMASK); - reason = cpu_vma_lbp(t32,0,PC-1,intrq,debug); + reason = cpu_vma_lbp(t32,0,PR-1,intrq,debug); break; } @@ -1386,7 +1387,7 @@ if (pattern != OP_N) { } if (debug) { /* debugging? */ - fprintf (sim_deb, ">>CPU EMA: PC = %06o, IR = %06o (", err_PC,IR); /* print preamble and IR */ + fprintf (sim_deb, ">>CPU EMA: P = %06o, IR = %06o (", err_PC,IR); /* print preamble and IR */ fprint_sym (sim_deb, err_PC, (t_value *) &IR, /* print instruction mnemonic */ NULL, SWMASK('M')); fputc (')', sim_deb); @@ -1399,11 +1400,11 @@ switch (entry) { /* decode IR<3:0> */ case 000: /* .EMIO 105240 (OP_A) */ rtn = op[0].word; reason = cpu_ema_emio(&rtn, op[1].word, - op[2].word, PC, debug); /* handle the EMIO instruction */ - PC = rtn; + op[2].word, PR, debug); /* handle the EMIO instruction */ + PR = rtn; if (debug) fprintf (sim_deb, ">>CPU EMA: return .EMIO: AR = %06o, BR = %06o, rtn=%s\n", - AR, BR, PC==op[0].word?"error":"good"); + AR, BR, PR==op[0].word?"error":"good"); break; case 001: /* .MMAP 105241 (OP_AKK) */ @@ -1426,11 +1427,11 @@ switch (entry) { /* decode IR<3:0> */ case 017: /* .EMAP 105247 (OP_A) */ rtn = op[0].word; /* error return */ reason = cpu_ema_emap(&rtn, op[1].word, - op[2].word, PC, debug); /* handle the EMAP instruction */ - PC = rtn; + op[2].word, PR, debug); /* handle the EMAP instruction */ + PR = rtn; if (debug) { fprintf (sim_deb, ">>CPU EMA: return .EMAP: AR = %06o, BR = %06o, rtn=%s\n", - AR, BR, PC==op[0].word?"error":"good"); + AR, BR, PR==op[0].word?"error":"good"); } break; diff --git a/HP2100/hp2100_cpu6.c b/HP2100/hp2100_cpu6.c index a26d66a7..6654bd8f 100644 --- a/HP2100/hp2100_cpu6.c +++ b/HP2100/hp2100_cpu6.c @@ -25,6 +25,7 @@ CPU6 RTE-6/VM OS instructions + 05-Aug-16 JDB Renamed the P register from "PC" to "PR" 17-May-16 JDB Set local variable instead of call parameter for .SIP test 24-Dec-14 JDB Added casts for explicit downward conversions 18-Mar-13 JDB Use MP abort handler declaration in hp2100_cpu.h @@ -244,7 +245,7 @@ t_stat reason = SCPE_OK; save_area = ReadW (xsusp); /* addr of PABEO save area */ -WriteW (save_area + 0, PC); /* save P */ +WriteW (save_area + 0, PR); /* save P */ WriteW (save_area + 1, AR); /* save A */ WriteW (save_area + 2, BR); /* save B */ WriteW (save_area + 3, (E << 15) & SIGN | O & 1); /* save E and O */ @@ -288,13 +289,13 @@ return reason; static t_stat cpu_save_state (uint32 iotrap) { uint16 vectors; -uint32 saved_PC, int_sys_off; +uint32 saved_PR, int_sys_off; t_stat reason; -saved_PC = PC; /* save current PC */ +saved_PR = PR; /* save current P register */ reason = iogrp (SFS_0_C, iotrap); /* turn interrupt system off */ -int_sys_off = (PC == saved_PC); /* set flag if already off */ -PC = saved_PC; /* restore PC in case it bumped */ +int_sys_off = (PR == saved_PR); /* set flag if already off */ +PR = saved_PR; /* restore P in case it bumped */ vectors = ReadW (vctr); /* get address of vectors (in SMAP) */ @@ -433,7 +434,7 @@ switch (entry) { /* decode IR<3:0> */ dms_ump = SMAP; /* set system map */ vectors = ReadW (vctr); /* get address of vectors (in SMAP) */ - PC = ReadW (vectors + mper_offset); /* vector to $MPER for processing */ + PR = ReadW (vectors + mper_offset); /* vector to $MPER for processing */ } else { /* privileged call */ @@ -444,9 +445,9 @@ switch (entry) { /* decode IR<3:0> */ save_area = ReadW (xsusp); /* get addr of P save area */ if (dms_ump) /* user map current? */ - WriteWA (save_area, (PC - 2) & VAMASK); /* set point of suspension */ + WriteWA (save_area, (PR - 2) & VAMASK); /* set point of suspension */ else /* system map current */ - WriteW (save_area, (PC - 2) & VAMASK); /* set point of suspension */ + WriteW (save_area, (PR - 2) & VAMASK); /* set point of suspension */ } WriteW (pvcn, (ReadW (pvcn) + 1) & DMASK); /* increment priv nest counter */ @@ -454,7 +455,7 @@ switch (entry) { /* decode IR<3:0> */ break; case 001: /* $LIBX 105341 (OP_A) */ - PC = ReadW (op[0].word); /* set P to return point */ + PR = ReadW (op[0].word); /* set P to return point */ count = (ReadW (pvcn) - 1) & DMASK; /* decrement priv nest counter */ WriteW (pvcn, count); /* write it back */ @@ -462,7 +463,7 @@ switch (entry) { /* decode IR<3:0> */ dms_ump = SMAP; /* set system map */ reason = cpu_save_regs (iotrap); /* save registers */ vectors = ReadW (vctr); /* get address of vectors */ - PC = ReadW (vectors + lxnd_offset); /* vector to $LXND for processing */ + PR = ReadW (vectors + lxnd_offset); /* vector to $LXND for processing */ } break; @@ -485,7 +486,7 @@ switch (entry) { /* decode IR<3:0> */ } while ((BR > 0) && (eqt != 0)); /* loop until timeout or done */ if (BR == 0) /* which termination condition? */ - PC = (PC + 1) & VAMASK; /* P+1 return for no timeout */ + PR = (PR + 1) & VAMASK; /* P+1 return for no timeout */ if (debug_print) /* debugging? */ fprint_regs ("; result:", /* print return registers */ @@ -522,7 +523,7 @@ switch (entry) { /* decode IR<3:0> */ AR = (key + 15) & DMASK; /* A = addr of IDSEG [15] */ BR = key; /* B = addr of IDSEG [0] */ E = (uint32) ((test[5] >> 4) & 1); /* E = short ID segment bit */ - PC = (PC + 1) & VAMASK; /* P+1 for found return */ + PR = (PR + 1) & VAMASK; /* P+1 for found return */ break; } @@ -537,24 +538,24 @@ switch (entry) { /* decode IR<3:0> */ break; case 004: /* .STIO 105344 (OP_A) */ - count = op[0].word - PC; /* get count of operands */ + count = op[0].word - PR; /* get count of operands */ if (debug_print) /* debugging? */ fprintf (sim_deb, /* print registers on entry */ ", A = %06o, count = %d", AR, count); for (i = 0; i < count; i++) { - ma = ReadW (PC); /* get operand address */ + ma = ReadW (PR); /* get operand address */ reason = resolve (ma, &ma, intrq); /* resolve indirect */ if (reason != SCPE_OK) { /* resolution failed? */ - PC = err_PC; /* IRQ restarts instruction */ + PR = err_PC; /* IRQ restarts instruction */ break; } WriteW (ma, ReadW (ma) & ~I_DEVMASK | AR); /* set SC into instruction */ - PC = (PC + 1) & VAMASK; /* bump to next */ + PR = (PR + 1) & VAMASK; /* bump to next */ } break; @@ -566,7 +567,7 @@ switch (entry) { /* decode IR<3:0> */ key = ReadW (BR); /* read a buffer word */ if (key == AR) { /* does it match? */ - PC = (PC + 1) & VAMASK; /* P+1 found return */ + PR = (PR + 1) & VAMASK; /* P+1 found return */ break; } @@ -633,9 +634,9 @@ switch (entry) { /* decode IR<3:0> */ } if (AR == 0) /* exhausted list? */ - PC = (PC + 1) & VAMASK; /* P+1 arg not found */ + PR = (PR + 1) & VAMASK; /* P+1 arg not found */ else if ((AR & SIGN) == 0) /* good link? */ - PC = (PC + 2) & VAMASK; /* P+2 arg found */ + PR = (PR + 2) & VAMASK; /* P+2 arg found */ /* P+0 bad link */ if (debug_print) /* debugging? */ fprint_regs ("; result:", /* print return registers */ @@ -649,25 +650,25 @@ switch (entry) { /* decode IR<3:0> */ reason = iogrp (CLF_0, iotrap); /* turn interrupt system off */ if (irq) /* was interrupt pending? */ - PC = (PC + 1) & VAMASK; /* P+1 return for pending IRQ */ + PR = (PR + 1) & VAMASK; /* P+1 return for pending IRQ */ /* P+0 return for no pending IRQ */ if (debug_print) /* debugging? */ fprintf (sim_deb, /* print return registers */ ", CIR = %02o, return = P+%d", - irq, PC - (err_PC + 1)); + irq, PR - (err_PC + 1)); break; case 011: /* .YLD 105351 (OP_C) */ - PC = op[0].word; /* pick up point of resumption */ + PR = op[0].word; /* pick up point of resumption */ reason = iogrp (STF_0, iotrap); /* turn interrupt system on */ ion_defer = 0; /* kill defer so irq occurs immed */ break; case 012: /* .CPM 105352 (OP_KK) */ if (INT16 (op[0].word) > INT16 (op[1].word)) - PC = (PC + 2) & VAMASK; /* P+2 arg1 > arg2 */ + PR = (PR + 2) & VAMASK; /* P+2 arg1 > arg2 */ else if (INT16 (op[0].word) < INT16 (op[1].word)) - PC = (PC + 1) & VAMASK; /* P+1 arg1 < arg2 */ + PR = (PR + 1) & VAMASK; /* P+1 arg1 < arg2 */ /* P+0 arg1 = arg2 */ if (debug_print) /* debugging? */ fprint_regs (",", REG_P_REL, err_PC + 3); /* print return registers */ @@ -698,7 +699,7 @@ switch (entry) { /* decode IR<3:0> */ } else { /* .ENTN instruction */ - ma = (PC - 2) & VAMASK; /* get addr of entry point */ + ma = (PR - 2) & VAMASK; /* get addr of entry point */ ENTX: /* enter here from .ENTC */ reason = cpu_ops (OP_A, op, intrq); /* get instruction operand */ @@ -719,7 +720,7 @@ switch (entry) { /* decode IR<3:0> */ reason = resolve (ma, &ma, intrq); /* resolve indirect */ if (reason != SCPE_OK) { /* resolution failed? */ - PC = err_PC; /* irq restarts instruction */ + PR = err_PC; /* irq restarts instruction */ break; } @@ -738,13 +739,13 @@ switch (entry) { /* decode IR<3:0> */ vectors = ReadW (vctr); /* get address of vectors (in SMAP) */ if (mp_viol & SIGN) { /* parity error? */ - WriteW (vectors + cic_offset, PC); /* save point of suspension in $CIC */ - PC = ReadW (vectors + perr_offset); /* vector to $PERR for processing */ + WriteW (vectors + cic_offset, PR); /* save point of suspension in $CIC */ + PR = ReadW (vectors + perr_offset); /* vector to $PERR for processing */ } else { /* MP/DMS violation */ cpu_save_regs (iotrap); /* save CPU registers */ - PC = ReadW (vectors + rqst_offset); /* vector to $RQST for processing */ + PR = ReadW (vectors + rqst_offset); /* vector to $RQST for processing */ } if (debug_print) { /* debugging? */ @@ -763,7 +764,7 @@ switch (entry) { /* decode IR<3:0> */ YR = 0000000; /* RPL switch (not implemented) */ AR = 0000000; /* LDR [B] (not implemented) */ SR = 0102077; /* test passed code */ - PC = (PC + 1) & VAMASK; /* P+1 return for firmware OK */ + PR = (PR + 1) & VAMASK; /* P+1 return for firmware OK */ if ((cpu_dev.dctrl & DEB_OS) && /* OS debug flag set, */ (sim_deb == NULL)) /* but debugging disabled? */ @@ -786,11 +787,11 @@ switch (entry) { /* decode IR<3:0> */ vectors = ReadW (vctr); /* get address of vectors (in SMAP) */ if (INT16 (AR) < 0) /* negative (program ID)? */ - PC = ReadW (vectors + sked_offset); /* vector to $SKED for processing */ + PR = ReadW (vectors + sked_offset); /* vector to $SKED for processing */ else if (AR > 0) /* positive (EQT address)? */ - PC = ReadW (vectors + cic2_offset); /* vector to $CIC2 for processing */ + PR = ReadW (vectors + cic2_offset); /* vector to $CIC2 for processing */ else /* zero (illegal interrupt) */ - PC = ReadW (vectors + cic4_offset); /* vector to $CIC4 for processing */ + PR = ReadW (vectors + cic4_offset); /* vector to $CIC4 for processing */ if (debug_print) /* debugging? */ fprintf (sim_deb, /* print return registers */ @@ -799,7 +800,7 @@ switch (entry) { /* decode IR<3:0> */ } else { /* .ENTC instruction */ - ma = (PC - 4) & VAMASK; /* get addr of entry point */ + ma = (PR - 4) & VAMASK; /* get addr of entry point */ goto ENTX; /* continue with common processing */ } break; @@ -808,7 +809,7 @@ switch (entry) { /* decode IR<3:0> */ if (iotrap) { /* in trap cell? */ reason = cpu_save_state (iotrap); /* TBG interrupt */ vectors = ReadW (vctr); /* get address of vectors (in SMAP) */ - PC = ReadW (vectors + clck_offset); /* vector to $CLCK for processing */ + PR = ReadW (vectors + clck_offset); /* vector to $CLCK for processing */ if (debug_print) /* debugging? */ fprint_regs (",", REG_CIR, 0); /* print interrupt source */ diff --git a/HP2100/hp2100_cpu7.c b/HP2100/hp2100_cpu7.c index 4f4cbb78..4a8cd721 100644 --- a/HP2100/hp2100_cpu7.c +++ b/HP2100/hp2100_cpu7.c @@ -1,7 +1,7 @@ /* hp2100_cpu7.c: HP 1000 VIS and SIGNAL/1000 microcode Copyright (c) 2008, Holger Veit - Copyright (c) 2006-2014, J. David Bryan + Copyright (c) 2006-2016, J. David Bryan Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -26,6 +26,7 @@ CPU7 Vector Instruction Set and SIGNAL firmware + 05-Aug-16 JDB Renamed the P register from "PC" to "PR" 24-Dec-14 JDB Added casts for explicit downward conversions 18-Mar-13 JDB Moved EMA helper declarations to hp2100_cpu1.h 09-May-12 JDB Separated assignments from conditional expressions @@ -375,19 +376,19 @@ entry = IR & 017; /* mask to entry point pattern = op_vis[entry]; if (entry==0) { /* retrieve sub opcode */ - ret = ReadOp (PC, in_s); /* get it */ + ret = ReadOp (PR, in_s); /* get it */ subcode = ret.word; if (subcode & 0100000) /* special property of ucode */ subcode = AR; /* for reentry */ - PC = (PC + 1) & VAMASK; /* bump to real argument list */ + PR = (PR + 1) & VAMASK; /* bump to real argument list */ pattern = (subcode & 0400) ? OP_AAKAKK : OP_AKAKAKK; /* scalar or vector operation */ } if (pattern != OP_N) { if (op_ftnret[entry]) { /* most VIS instrs ignore RTN addr */ - ret = ReadOp(PC, in_s); + ret = ReadOp(PR, in_s); rtn = rtn1 = ret.word; /* but save it just in case */ - PC = (PC + 1) & VAMASK; /* move to next argument */ + PR = (PR + 1) & VAMASK; /* move to next argument */ } reason = cpu_ops (pattern, op, intrq); /* get instruction operands */ if (reason != SCPE_OK) /* evaluation failed? */ @@ -445,17 +446,17 @@ switch (entry) { /* decode IR<3:0> */ vis_movswp(op,opsize,TRUE); break; case 014: /* .ERES (OP_(A)AA) */ - reason = cpu_ema_eres(&rtn,op[2].word,PC,debug); /* handle the ERES instruction */ - PC = rtn; + reason = cpu_ema_eres(&rtn,op[2].word,PR,debug); /* handle the ERES instruction */ + PR = rtn; if (debug) fprintf (sim_deb, ">>CPU VIS: return .ERES: AR = %06o, BR = %06o, rtn=%s\n", - AR, BR, PC==op[0].word ? "error" : "good"); + AR, BR, PR==op[0].word ? "error" : "good"); break; case 015: /* .ESEG (OP_(A)A) */ reason = cpu_ema_eseg(&rtn,IR,op[0].word,debug); /* handle the ESEG instruction */ - PC = rtn; + PR = rtn; if (debug) fprintf (sim_deb, ">>CPU VIS: return .ESEG: AR = %06o , BR = %06o, rtn=%s\n", @@ -464,7 +465,7 @@ switch (entry) { /* decode IR<3:0> */ case 016: /* .VSET (OP_(A)AAACCC) */ reason = cpu_ema_vset(&rtn,op,debug); - PC = rtn; + PR = rtn; if (debug) fprintf (sim_deb, ">>CPU VIS: return .VSET: AR = %06o BR = %06o, rtn=%s\n", AR, BR, @@ -474,7 +475,7 @@ switch (entry) { /* decode IR<3:0> */ case 017: /* [test] (OP_N) */ XR = 3; /* firmware revision */ SR = 0102077; /* test passed code */ - PC = (PC + 1) & VAMASK; /* P+2 return for firmware w/VIS */ + PR = (PR + 1) & VAMASK; /* P+2 return for firmware w/VIS */ break; default: /* others undefined */ reason = stop_inst; @@ -680,7 +681,7 @@ switch (entry) { /* decode IR<3:0> */ * Given a complex*8 vector of nbits (power of 2), this calculates: * swap( vect[idx], vect[rev(idx)]) where rev(i) is the bitreversed value of i */ sig_bitrev(op[1].word, op[1].word+2, op[2].word-1, op[3].word, 4); - PC = op[0].word & VAMASK; + PR = op[0].word & VAMASK; break; case 001: /* BTRFY (OP_AAFFKK) */ @@ -695,7 +696,7 @@ switch (entry) { /* decode IR<3:0> */ sig_btrfy(op[1].word, op[1].word+2, op[2], op[3], 2*(op[4].word-1), 2*op[5].word); - PC = op[0].word & VAMASK; + PR = op[0].word & VAMASK; break; case 002: /* UNSCR (OP_AAFFKK) */ @@ -729,7 +730,7 @@ switch (entry) { /* decode IR<3:0> */ WriteOp(RE(v + idx2), p1, fp_f); (void)fp_exec(020, &p2, d, m2); /* VI[idx2] := 0.5*(p3-p4) - imag(W*(c,d)) */ WriteOp(IM(v + idx2), p2, fp_f); - PC = op[0].word & VAMASK; + PR = op[0].word & VAMASK; break; case 003: /* PRSCR (OP_AAFFKK) */ @@ -763,7 +764,7 @@ switch (entry) { /* decode IR<3:0> */ WriteOp(RE(v + idx2), p1, fp_f); (void)fp_exec(020, &p2, m1, d); /* VI[idx2] := imag(W*(c,d)) - (p3-p4) */ WriteOp(IM(v + idx2), p2, fp_f); - PC = op[0].word & VAMASK; + PR = op[0].word & VAMASK; break; case 004: /* BITR1 (OP_AAAKK) */ @@ -782,7 +783,7 @@ switch (entry) { /* decode IR<3:0> */ * difference to BITRV is that BITRV uses complex*8, and BITR1 uses separate real*4 * vectors for Real and Imag parts */ sig_bitrev(op[1].word, op[2].word, op[3].word-1, op[4].word, 2); - PC = op[0].word & VAMASK; + PR = op[0].word & VAMASK; break; @@ -799,7 +800,7 @@ switch (entry) { /* decode IR<3:0> */ sig_btrfy(op[1].word, op[2].word, op[3], op[4], op[5].word-1, op[6].word); - PC = op[0].word & VAMASK; + PR = op[0].word & VAMASK; break; case 006: /* .CADD (OP_AAA) */ @@ -928,7 +929,7 @@ switch (entry) { /* decode IR<3:0> */ case 017: /* [slftst] (OP_N) */ XR = 2; /* firmware revision */ SR = 0102077; /* test passed code */ - PC = (PC + 1) & VAMASK; /* P+2 return for firmware w/SIGNAL1000 */ + PR = (PR + 1) & VAMASK; /* P+2 return for firmware w/SIGNAL1000 */ break; case 016: /* invalid */ diff --git a/HP2100/hp2100_defs.h b/HP2100/hp2100_defs.h index 7de6bc69..9034e977 100644 --- a/HP2100/hp2100_defs.h +++ b/HP2100/hp2100_defs.h @@ -23,8 +23,9 @@ be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization from Robert M Supnik. + 05-Aug-16 JDB Removed PC_Global renaming; P register is now "PR" 13-May-16 JDB Modified for revised SCP API function parameter types - 19-Jun-15 JDB Conditionally use Global_PC for PC for version 4.0 and on + 19-Jun-15 JDB Conditionally use PC_Global for PC for version 4.0 and on 30-Dec-14 JDB Added S-register parameters to ibl_copy, more IBL constants 28-Dec-14 JDB Changed suppression from #pragma GCC to #pragma clang 05-Feb-13 JDB Added declaration for hp_fprint_stopped @@ -84,10 +85,6 @@ #include "sim_defs.h" -#if (SIM_MAJOR >= 4) - #define PC PC_Global /* Rename to avoid namespace conflicts */ -#endif - /* The following pragmas quell clang warnings that are on by default but should not be, in my opinion. They warn about the use of perfectly valid code and diff --git a/HP2100/hp2100_disclib.c b/HP2100/hp2100_disclib.c index 4690e381..2bc63514 100644 --- a/HP2100/hp2100_disclib.c +++ b/HP2100/hp2100_disclib.c @@ -2296,7 +2296,7 @@ cvptr->buffer [index] = (uint16) cvptr->cylinder /* update the cylind + (cvptr->eoc == SET ? 1 : 0); cvptr->buffer [index + 1] = SET_HEAD (cvptr) /* merge the head and sector */ - | SET_SECTOR (cvptr); + | SET_SECTOR (cvptr); return; } diff --git a/HP2100/hp2100_dr.c b/HP2100/hp2100_dr.c index 1ce86281..fdb33eeb 100644 --- a/HP2100/hp2100_dr.c +++ b/HP2100/hp2100_dr.c @@ -26,6 +26,7 @@ DR 12606B 2770/2771 fixed head disk 12610B 2773/2774/2775 drum + 05-Aug-16 JDB Renamed the P register from "PC" to "PR" 13-May-16 JDB Modified for revised SCP API function parameter types 30-Dec-14 JDB Added S-register parameters to ibl_copy 24-Dec-14 JDB Added casts for explicit downward conversions @@ -744,9 +745,9 @@ if (unitno != 0) /* boot supported on dri if (ibl_copy (dr_rom, dev, IBL_S_NOCLR, IBL_S_NOSET)) /* copy the boot ROM to memory and configure */ return SCPE_IERR; /* return an internal error if the copy failed */ -WritePW (PC + IBL_DPC, dr_rom [IBL_DPC]); /* restore overwritten word */ -WritePW (PC + IBL_END, dr_rom [IBL_END]); /* restore overwritten word */ -PC = PC + BOOT_START; /* correct starting address */ +WritePW (PR + IBL_DPC, dr_rom [IBL_DPC]); /* restore overwritten word */ +WritePW (PR + IBL_END, dr_rom [IBL_END]); /* restore overwritten word */ +PR = PR + BOOT_START; /* correct starting address */ return SCPE_OK; } diff --git a/HP2100/hp2100_ipl.c b/HP2100/hp2100_ipl.c index 3b42ac06..84546db4 100644 --- a/HP2100/hp2100_ipl.c +++ b/HP2100/hp2100_ipl.c @@ -25,6 +25,7 @@ IPLI, IPLO 12875A interprocessor link + 05-Aug-16 JDB Renamed the P register from "PC" to "PR" 13-May-16 JDB Modified for revised SCP API function parameter types 14-Sep-15 JDB Exposed "ipl_edtdelay" via a REG_HIDDEN to allow user tuning Corrected typos in comments and strings @@ -866,10 +867,10 @@ if (ibl_copy (ipl_rom, devi, IBL_S_CLR, /* copy the boot ROM to IBL_SET_SC (devi) | devp)) /* the S register accordingly */ return SCPE_IERR; /* return an internal error if the copy failed */ -WritePW (PC + MAX_BASE, (~PC + 1) & DMASK); /* fix ups */ -WritePW (PC + IPL_PNTR, ipl_rom [IPL_PNTR] | PC); -WritePW (PC + PTR_PNTR, ipl_rom [PTR_PNTR] | PC); -WritePW (PC + IPL_DEVA, devi); -WritePW (PC + PTR_DEVA, devp); +WritePW (PR + MAX_BASE, (~PR + 1) & DMASK); /* fix ups */ +WritePW (PR + IPL_PNTR, ipl_rom [IPL_PNTR] | PR); +WritePW (PR + PTR_PNTR, ipl_rom [PTR_PNTR] | PR); +WritePW (PR + IPL_DEVA, devi); +WritePW (PR + PTR_DEVA, devp); return SCPE_OK; } diff --git a/HP2100/hp2100_mpx.c b/HP2100/hp2100_mpx.c index fa913bc3..607b5f7e 100644 --- a/HP2100/hp2100_mpx.c +++ b/HP2100/hp2100_mpx.c @@ -25,6 +25,7 @@ MPX 12792C 8-channel multiplexer card + 02-Aug-16 JDB Burst-fill only the first receive buffer in fast mode 28-Jul-16 JDB Fixed buffer ready check at read completion Fixed terminate on character counts > 254 13-May-16 JDB Modified for revised SCP API function parameter types @@ -1670,6 +1671,7 @@ return SCPE_OK; buffer full), and if observed, the read buffer is terminated, and a read buffer available UI condition is signalled. + Implementation notes: 1. The firmware echoes an entered BS before checking the buffer count to see @@ -1680,6 +1682,12 @@ return SCPE_OK; processing. Instead, a pair of characters are sought on line 0 to fill the input buffer. When they are received, the device flag is set. The CPU will do a LIx sc,C to retrieve the data and reset the flag. + + 3. In fast timing mode, burst transfers are used only to fill the first of + the two receive buffers; the second is filled with one character per + service entry. This allows the CPU time to unload the first buffer + before the second fills up. Once the first buffer is freed, the routine + shifts back to burst mode to fill the remainder of the second buffer. */ t_stat mpx_line_svc (UNIT *uptr) @@ -1690,109 +1698,122 @@ const uint32 data_bits = 5 + GET_BPC (mpx_config [port]); /* number of dat const uint32 data_mask = (1 << data_bits) - 1; /* mask for data bits */ const t_bool fast_timing = (uptr->flags & UNIT_FASTTIME) != 0; /* port is set for fast timing */ const t_bool fast_binary_read = (mpx_cmd == CMD_BINARY_READ); /* fast binary read in progress */ - uint8 ch; int32 chx; +uint32 buffer_count, write_count; t_stat status = SCPE_OK; t_bool recv_loop = !fast_binary_read; /* bypass if fast binary read */ t_bool xmit_loop = !(fast_binary_read || /* bypass if fast read or output suspended */ (mpx_flags [port] & (FL_WAITACK | FL_XOFF))); +if (DEBUG_PRI (mpx_dev, DEB_CMDS)) + fprintf (sim_deb, ">>MPX cmds: Port %d service entered\n", port); + /* Transmission service */ -while (xmit_loop && (buf_len (iowrite, port, get) > 0)) { /* character available to output? */ - if ((mpx_flags [port] & FL_WREMPT) == 0) { /* has buffer started emptying? */ - chx = buf_get (iowrite, port) << 8; /* get header value and position */ +write_count = buf_len (iowrite, port, get); /* get the output buffer length */ - if (fast_timing || (chx & WR_NO_ENQACK) || /* do we want handshake? */ - !(mpx_config [port] & SK_ENQACK)) /* and configured for handshake? */ - mpx_flags [port] &= ~FL_DO_ENQACK; /* no, so clear flag */ +while (xmit_loop && write_count > 0) { /* character available to output? */ + if ((mpx_flags [port] & FL_WREMPT) == 0) { /* if the buffer has not started emptying */ + chx = buf_get (iowrite, port) << 8; /* then get the header value and position it */ + + if (fast_timing || (chx & WR_NO_ENQACK) || /* do we want handshake? */ + !(mpx_config [port] & SK_ENQACK)) /* and configured for handshake? */ + mpx_flags [port] &= ~FL_DO_ENQACK; /* no, so clear flag */ else - mpx_flags [port] |= FL_DO_ENQACK; /* yes, so set flag */ + mpx_flags [port] |= FL_DO_ENQACK; /* yes, so set flag */ - continue; /* "continue" for zero-length write */ + continue; /* continue with the first output character */ } - if (mpx_flags [port] & FL_DO_ENQACK) /* do handshake for this buffer? */ - mpx_enq_cntr [port] = mpx_enq_cntr [port] + 1; /* bump character counter */ + if (mpx_flags [port] & FL_DO_ENQACK) /* do handshake for this buffer? */ + mpx_enq_cntr [port] = mpx_enq_cntr [port] + 1; /* bump character counter */ - if (mpx_enq_cntr [port] > ENQ_LIMIT) { /* ready for ENQ? */ - mpx_enq_cntr [port] = 0; /* clear ENQ counter */ - mpx_ack_wait [port] = 0; /* clear ACK wait timer */ + if (mpx_enq_cntr [port] > ENQ_LIMIT) { /* ready for ENQ? */ + mpx_enq_cntr [port] = 0; /* clear ENQ counter */ + mpx_ack_wait [port] = 0; /* clear ACK wait timer */ - mpx_flags [port] |= FL_WAITACK; /* set wait for ACK */ + mpx_flags [port] |= FL_WAITACK; /* set wait for ACK */ ch = ENQ; - status = tmxr_putc_ln (&mpx_ldsc [port], ch); /* transmit ENQ */ - xmit_loop = FALSE; /* stop further transmission */ + status = tmxr_putc_ln (&mpx_ldsc [port], ch); /* transmit ENQ */ + xmit_loop = FALSE; /* stop further transmission */ } - else { /* not ready for ENQ */ - ch = buf_get (iowrite, port) & data_mask; /* get char and mask to bit width */ - status = tmxr_putc_ln (&mpx_ldsc [port], ch); /* transmit the character */ - xmit_loop = (status == SCPE_OK) && fast_timing; /* continue transmission? */ + else { /* not ready for ENQ */ + ch = buf_get (iowrite, port) & data_mask; /* get char and mask to bit width */ + status = tmxr_putc_ln (&mpx_ldsc [port], ch); /* transmit the character */ + + write_count = write_count - 1; /* count the character */ + xmit_loop = (status == SCPE_OK) && fast_timing; /* and continue transmission if enabled */ } - if ((status == SCPE_OK) && /* transmitted OK? */ - DEBUG_PRI (mpx_dev, DEB_XFER)) + if (status != SCPE_OK) /* if the transmission failed */ + xmit_loop = FALSE; /* then exit the loop */ + + else if (DEBUG_PRI (mpx_dev, DEB_XFER)) fprintf (sim_deb, ">>MPX xfer: Port %d character %s transmitted\n", port, fmt_char (ch)); - else - xmit_loop = FALSE; + if (write_count == 0) { /* buffer complete? */ + buf_free (iowrite, port); /* free buffer */ - if (buf_len (iowrite, port, get) == 0) { /* buffer complete? */ - buf_free (iowrite, port); /* free buffer */ + write_count = buf_len (iowrite, port, get); /* get the next output buffer length */ - if (mpx_state == idle) /* controller idle? */ - mpx_cntl_svc (&mpx_cntl); /* check for UI */ + if (mpx_state == idle) /* controller idle? */ + mpx_cntl_svc (&mpx_cntl); /* check for UI */ } } /* Reception service */ -while (recv_loop) { /* OK to process? */ - chx = tmxr_getc_ln (&mpx_ldsc [port]); /* get a new character */ +buffer_count = buf_avail (ioread, port); /* get the number of available read buffers */ - if (chx == 0) /* if there are no more characters available */ - break; /* then quit the reception loop */ +if (mpx_flags [port] & FL_RDFILL) /* if filling the current buffer */ + buffer_count = buffer_count + 1; /* then include it in the count */ - if (chx & SCPE_BREAK) { /* break detected? */ - mpx_flags [port] |= FL_BREAK; /* set break status */ +while (recv_loop) { /* OK to process? */ + chx = tmxr_getc_ln (&mpx_ldsc [port]); /* get a new character */ + + if (chx == 0) /* if there are no more characters available */ + break; /* then quit the reception loop */ + + if (chx & SCPE_BREAK) { /* break detected? */ + mpx_flags [port] |= FL_BREAK; /* set break status */ if (DEBUG_PRI (mpx_dev, DEB_XFER)) fputs (">>MPX xfer: Break detected\n", sim_deb); - if (mpx_state == idle) /* controller idle? */ - mpx_cntl_svc (&mpx_cntl); /* check for UI */ + if (mpx_state == idle) /* controller idle? */ + mpx_cntl_svc (&mpx_cntl); /* check for UI */ - continue; /* discard NUL that accompanied BREAK */ + continue; /* discard NUL that accompanied BREAK */ } - ch = (uint8) (chx & data_mask); /* mask to bits per char */ + ch = (uint8) (chx & data_mask); /* mask to bits per char */ - if ((ch == XOFF) && /* XOFF? */ - (mpx_flowcntl [port] & FC_XONXOFF)) { /* and handshaking enabled? */ - mpx_flags [port] |= FL_XOFF; /* suspend transmission */ + if ((ch == XOFF) && /* XOFF? */ + (mpx_flowcntl [port] & FC_XONXOFF)) { /* and handshaking enabled? */ + mpx_flags [port] |= FL_XOFF; /* suspend transmission */ if (DEBUG_PRI (mpx_dev, DEB_XFER)) fprintf (sim_deb, ">>MPX xfer: Port %d character XOFF " "suspends transmission\n", port); - recv_loop = fast_timing; /* set to loop if fast mode */ + recv_loop = fast_timing; /* set to loop if fast mode */ continue; } - else if ((ch == XON) && /* XON? */ - (mpx_flags [port] & FL_XOFF)) { /* and currently suspended? */ - mpx_flags [port] &= ~FL_XOFF; /* resume transmission */ + else if ((ch == XON) && /* XON? */ + (mpx_flags [port] & FL_XOFF)) { /* and currently suspended? */ + mpx_flags [port] &= ~FL_XOFF; /* resume transmission */ if (DEBUG_PRI (mpx_dev, DEB_XFER)) fprintf (sim_deb, ">>MPX xfer: Port %d character XON " "resumes transmission\n", port); - recv_loop = fast_timing; /* set to loop if fast mode */ + recv_loop = fast_timing; /* set to loop if fast mode */ continue; } @@ -1805,7 +1826,7 @@ while (recv_loop) { /* OK to process? */ recv_loop = FALSE; /* absorb character */ } - else if ((buf_avail (ioread, port) == 0) && /* no free buffer available for char? */ + else if (buffer_count == 0 && /* no free buffer available for char? */ !(mpx_flags [port] & FL_RDFILL)) { /* and not filling last buffer? */ mpx_flags [port] |= FL_RDOVFLOW; /* set buffer overflow flag */ recv_loop = fast_timing; /* continue loop if fast mode */ @@ -1893,10 +1914,13 @@ while (recv_loop) { /* OK to process? */ mpx_param = mpx_param | RS_PARTIAL; /* and partial buffer flag */ } - if (recv_loop) /* no termination condition? */ - recv_loop = fast_timing; /* set to loop if fast mode */ + if (recv_loop) /* if there is no termination condition */ + if (buffer_count == 2) /* then if we're filling the first buffer */ + recv_loop = fast_timing; /* then set to loop if in fast mode */ + else /* otherwise we're filling the second */ + recv_loop = FALSE; /* so give the CPU a chance to read the first */ - else { /* termination occurred */ + else { /* otherwise a termination condition exists */ if (DEBUG_PRI (mpx_dev, DEB_XFER)) { fprintf (sim_deb, ">>MPX xfer: Port %d read terminated on ", port); @@ -1955,10 +1979,15 @@ if (fast_binary_read) { /* fast binary read else { /* normal service */ tmxr_poll_tx (&mpx_desc); /* output any accumulated characters */ - if ((buf_avail (iowrite, port) < 2) && /* more to transmit? */ - !(mpx_flags [port] & (FL_WAITACK | FL_XOFF)) || /* and transmission not suspended */ - tmxr_rqln (&mpx_ldsc [port])) /* or more to receive? */ - sim_activate (uptr, uptr->wait); /* reschedule service */ + if (write_count > 0 /* if there are more characters to transmit */ + && !(mpx_flags [port] & (FL_WAITACK | FL_XOFF)) /* and transmission is not suspended */ + || tmxr_rqln (&mpx_ldsc [port])) { /* or there are more characters to receive */ + sim_activate (uptr, uptr->wait); /* then reschedule the service */ + + if (DEBUG_PRI (mpx_dev, DEB_CMDS)) + fprintf (sim_deb, ">>MPX cmds: Port %d delay %d service rescheduled\n", port, uptr->wait); + } + else if (DEBUG_PRI (mpx_dev, DEB_CMDS)) fprintf (sim_deb, ">>MPX cmds: Port %d service stopped\n", port); diff --git a/HP2100/hp2100_ms.c b/HP2100/hp2100_ms.c index a2f17646..1db27ae2 100644 --- a/HP2100/hp2100_ms.c +++ b/HP2100/hp2100_ms.c @@ -1314,7 +1314,7 @@ if (unitno != 0) /* boot supported on dri return SCPE_NOFNC; /* report "Command not allowed" if attempted */ if (ibl_copy (ms_rom, dev, IBL_OPT, /* copy the boot ROM to memory and configure */ - IBL_MS | IBL_SET_SC (dev))) /* the S register accordingly */ + IBL_MS | IBL_SET_SC (dev))) /* the S register accordingly */ return SCPE_IERR; /* return an internal error if the copy failed */ if ((sim_switches & SWMASK ('S')) && AR) /* if -S is specified and the A register is non-zero */