From 946bfd329f9f6624364b266dc66005151c3fc018 Mon Sep 17 00:00:00 2001 From: Mark Pizzolato Date: Sat, 13 Aug 2016 05:10:04 -0700 Subject: [PATCH] HP2100: Latest updates from Dave Bryan 273. ENHANCEMENT: Burst-fill only the first of two MPX receive buffers in FASTTIME mode. 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. 274. PROBLEM: A second connection to the BACI device leaves the client unresponsive. 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" unconditionally, so that a second concurrent connection attempt will be rejected with "All connections busy". 275. PROBLEM: The exported program counter name (PC) clashes with other libraries. 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. --- HP2100/hp2100_baci.c | 27 ++++--- HP2100/hp2100_bugfixes.txt | 108 ++++++++++++++++++++++++++-- HP2100/hp2100_cpu.c | 79 ++++++++++----------- HP2100/hp2100_cpu.h | 5 +- HP2100/hp2100_cpu1.c | 17 ++--- HP2100/hp2100_cpu2.c | 97 +++++++++++++------------- HP2100/hp2100_cpu3.c | 49 ++++++------- HP2100/hp2100_cpu4.c | 39 ++++++----- HP2100/hp2100_cpu5.c | 87 +++++++++++------------ HP2100/hp2100_cpu6.c | 71 +++++++++---------- HP2100/hp2100_cpu7.c | 37 +++++----- HP2100/hp2100_defs.h | 7 +- HP2100/hp2100_disclib.c | 2 +- HP2100/hp2100_dr.c | 7 +- HP2100/hp2100_ipl.c | 11 +-- HP2100/hp2100_mpx.c | 139 ++++++++++++++++++++++--------------- HP2100/hp2100_ms.c | 2 +- 17 files changed, 463 insertions(+), 321 deletions(-) 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 */