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.
This commit is contained in:
Mark Pizzolato 2016-08-13 05:10:04 -07:00
parent 1c4a1ed871
commit 946bfd329f
17 changed files with 463 additions and 321 deletions

View file

@ -25,6 +25,7 @@
BACI 12966A BACI card 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 13-May-16 JDB Modified for revised SCP API function parameter types
24-Dec-14 JDB Added casts for explicit downward conversions 24-Dec-14 JDB Added casts for explicit downward conversions
10-Jan-13 MP Added DEV_MUX and additional DEVICE field values 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 scheduled. It starts when the socket is attached and stops when the socket
is detached. 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) t_stat baci_poll_svc (UNIT *uptr)
{ {
if (baci_term.flags & UNIT_ATT) { /* attached to line? */ if (tmxr_poll_conn (&baci_desc) >= 0) /* if new connection is established */
if ((baci_ldsc.conn == 0) && /* line not connected? */ baci_ldsc.rcve = 1; /* then enable line to receive */
(tmxr_poll_conn (&baci_desc) >= 0)) /* and new connection established? */
baci_ldsc.rcve = 1; /* 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? */ if (tmxr_rqln (&baci_ldsc)) /* chars available? */
sim_activate (&baci_term, baci_term.wait); /* activate I/O service */ sim_activate (&baci_term, baci_term.wait); /* activate I/O service */
}
if (uptr->wait == POLL_FIRST) /* first poll? */ if (uptr->wait == POLL_FIRST) /* first poll? */
uptr->wait = sync_poll (INITIAL); /* initial synchronization */ uptr->wait = sync_poll (INITIAL); /* initial synchronization */
@ -1063,18 +1066,20 @@ if (status == SCPE_OK) {
return status; return status;
} }
/* Detach controller */ /* Detach controller */
t_stat baci_detach (UNIT *uptr) t_stat baci_detach (UNIT *uptr)
{ {
t_stat status; t_stat status;
status = tmxr_detach (&baci_desc, uptr); /* detach socket */
baci_ldsc.rcve = 0; /* disable line reception */ baci_ldsc.rcve = 0; /* disable line reception */
sim_cancel (&baci_poll); /* stop Telnet poll */ sim_cancel (&baci_poll); /* stop Telnet poll */
status = tmxr_detach (&baci_desc, uptr); /* detach socket */
return status; return status;
} }
/* Local routines */ /* Local routines */

View file

@ -1,6 +1,6 @@
HP 2100 SIMULATOR BUG FIX WRITEUPS HP 2100 SIMULATOR FIXES
================================== =======================
Last update: 2016-07-28 Last update: 2016-08-05
1. PROBLEM: Booting from magnetic tape reports "HALT instruction, P: 77756 1. PROBLEM: Booting from magnetic tape reports "HALT instruction, P: 77756
@ -7016,3 +7016,103 @@
enabled and the values are equal. enabled and the values are equal.
STATUS: Fixed in version 4.0-0. 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.

View file

@ -29,6 +29,7 @@
DMA1,DMA2 12607B/12578A/12895A direct memory access controller DMA1,DMA2 12607B/12578A/12895A direct memory access controller
DCPC1,DCPC2 12897B dual channel port 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 13-May-16 JDB Modified for revised SCP API function parameter types
31-Dec-14 JDB Corrected devdisp data parameters 31-Dec-14 JDB Corrected devdisp data parameters
30-Dec-14 JDB Added S-register parameters to ibl_copy 30-Dec-14 JDB Added S-register parameters to ibl_copy
@ -183,7 +184,7 @@
AR<15:0> A register - addressable as location 0 AR<15:0> A register - addressable as location 0
BR<15:0> B register - addressable as location 1 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 SR<15:0> S register - switch register
MR<14:0> M register - memory address MR<14:0> M register - memory address
TR<15:0> T register - memory data TR<15:0> T register - memory data
@ -234,9 +235,9 @@
<15,10> mode action <15,10> mode action
0,0 page zero direct MA = IR<9:0> 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,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. Memory reference instructions can access an address space of 32K words.
An instruction can directly reference the first 1024 words of memory 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 *M = NULL; /* memory */
uint16 ABREG[2]; /* A/B registers */ uint16 ABREG[2]; /* A/B registers */
uint32 PC = 0; /* P register */ uint32 PR = 0; /* P register */
uint32 SR = 0; /* S register */ uint32 SR = 0; /* S register */
uint32 MR = 0; /* M register */ uint32 MR = 0; /* M register */
uint32 TR = 0; /* T 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) }; UNIT cpu_unit = { UDATA (NULL, UNIT_FIX + UNIT_BINK, 0) };
REG cpu_reg[] = { REG cpu_reg[] = {
{ ORDATA (P, PC, 15) }, { ORDATA (P, PR, 15) },
{ ORDATA (A, AR, 16), REG_FIT }, { ORDATA (A, AR, 16), REG_FIT },
{ ORDATA (B, BR, 16), REG_FIT }, { ORDATA (B, BR, 16), REG_FIT },
{ ORDATA (M, MR, 15) }, { 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 This routine is the instruction decode routine for the HP 2100. It is called
from the simulator control program to execute instructions in simulated 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. status other than SCPE_OK.
*/ */
@ -1034,7 +1035,7 @@ int abortval;
if (dev_conflict ()) /* check device assignment consistency */ if (dev_conflict ()) /* check device assignment consistency */
return SCPE_STOP; /* conflict; stop execution */ 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 */ /* Restore I/O state */
@ -1127,7 +1128,7 @@ intrq = calc_int (); /* initial recalc of int
while (reason == SCPE_OK) { /* loop until halted */ while (reason == SCPE_OK) { /* loop until halted */
uint32 IR, MA, absel, v1, t, skip; 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? */ if (sim_interval <= 0) { /* event timeout? */
reason = sim_process_event (); /* process event service */ 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 */ iotrap = 0; /* not a trap cell instruction */
if (sim_brk_summ && /* any breakpoints? */ 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_enb ? /* correct type for DMS state? */
(dms_ump ? (dms_ump ?
SWMASK ('U') : SWMASK ('S')) : SWMASK ('U') : SWMASK ('S')) :
@ -1294,10 +1295,10 @@ while (reason == SCPE_OK) { /* loop until halted */
} }
if (mp_evrff) /* violation register enabled */ 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 */ IR = ReadW (PR); /* fetch instr */
PC = (PC + 1) & VAMASK; PR = (PR + 1) & VAMASK;
ion_defer = FALSE; ion_defer = FALSE;
} }
@ -1359,9 +1360,9 @@ while (reason == SCPE_OK) { /* loop until halted */
mp_dms_jmp (MA, jsb_plb); /* validate jump address */ mp_dms_jmp (MA, jsb_plb); /* validate jump address */
WriteW (MA, PC); /* store PC */ WriteW (MA, PR); /* store P */
PCQ_ENTRY; PCQ_ENTRY;
PC = (MA + 1) & VAMASK; /* jump */ PR = (MA + 1) & VAMASK; /* jump */
break; break;
case 0040:case 0041:case 0042:case 0043: 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 */ mp_dms_jmp (MA, 0); /* validate jump addr */
PCQ_ENTRY; PCQ_ENTRY;
PC = MA; /* jump */ PR = MA; /* jump */
/* Idle conditions by operating system: /* 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 ((sim_idle_enab) && (intrq == 0)) /* idle enabled w/o pending irq? */
if (((PC == err_PC) || /* RTE through RTE-IVB */ if (((PR == err_PC) || /* RTE through RTE-IVB */
((PC == (err_PC - 1)) && /* RTE-6/VM */ ((PR == (err_PC - 1)) && /* RTE-6/VM */
((ReadW (PC) & I_MRG) == I_ISZ))) && /* RTE jump target */ ((ReadW (PR) & I_MRG) == I_ISZ))) && /* RTE jump target */
(mp_fence == CLEAR) && (M [xeqt] == 0) && /* RTE idle indications */ (mp_fence == CLEAR) && (M [xeqt] == 0) && /* RTE idle indications */
(M [tbg] == clk_dib.select_code) || /* RTE verification */ (M [tbg] == clk_dib.select_code) || /* RTE verification */
(PC == (err_PC - 3)) && /* DOS through DOS-III */ (PR == (err_PC - 3)) && /* DOS through DOS-III */
(ReadW (PC) == I_STF) && /* DOS jump target */ (ReadW (PR) == I_STF) && /* DOS jump target */
(AR == 0177777) && (BR == 0177777) && /* DOS idle indication */ (AR == 0177777) && (BR == 0177777) && /* DOS idle indication */
(M [m64] == 0177700) && /* DOS verification */ (M [m64] == 0177700) && /* DOS verification */
(M [p64] == 0000100)) /* DOS verification */ (M [p64] == 0000100)) /* DOS verification */
@ -1498,7 +1499,7 @@ while (reason == SCPE_OK) { /* loop until halted */
WriteW (MA, t); WriteW (MA, t);
if (t == 0) if (t == 0)
PC = (PC + 1) & VAMASK; PR = (PR + 1) & VAMASK;
break; break;
case 0100:case 0101:case 0102:case 0103: case 0100:case 0101:case 0102:case 0103:
@ -1553,7 +1554,7 @@ while (reason == SCPE_OK) { /* loop until halted */
break; /* stop execution */ break; /* stop execution */
if (AR != ReadW (MA)) if (AR != ReadW (MA))
PC = (PC + 1) & VAMASK; PR = (PR + 1) & VAMASK;
break; break;
case 0130:case 0131:case 0132:case 0133: case 0130:case 0131:case 0132:case 0133:
@ -1566,7 +1567,7 @@ while (reason == SCPE_OK) { /* loop until halted */
break; /* stop execution */ break; /* stop execution */
if (BR != ReadW (MA)) if (BR != ReadW (MA))
PC = (PC + 1) & VAMASK; PR = (PR + 1) & VAMASK;
break; break;
case 0140:case 0141:case 0142:case 0143: case 0140:case 0141:case 0142:case 0143:
@ -1702,7 +1703,7 @@ while (reason == SCPE_OK) { /* loop until halted */
} /* end if ~RSS */ } /* end if ~RSS */
ABREG[absel] = (uint16) t; /* store result */ 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 */ break; /* end if alter/skip */
/* Shift instructions */ /* Shift instructions */
@ -1715,7 +1716,7 @@ while (reason == SCPE_OK) { /* loop until halted */
E = 0; E = 0;
if ((IR & 000010) && ((t & 1) == 0)) /* SLx */ 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 */ ABREG[absel] = (uint16) shift (t, IR & 00020, IR); /* do second shift */
break; /* end if 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? */ 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 */ reason = SCPE_OK; /* continue */
} }
} /* end while */ } /* end while */
@ -1766,7 +1767,7 @@ while (reason == SCPE_OK) { /* loop until halted */
if (iotrap && (reason == STOP_HALT)) /* HLT in trap cell? */ if (iotrap && (reason == STOP_HALT)) /* HLT in trap cell? */
MR = intaddr; /* M = interrupt address */ MR = intaddr; /* M = interrupt address */
else /* normal HLT */ else /* normal HLT */
MR = (PC - 1) & VAMASK; /* M = P - 1 */ MR = (PR - 1) & VAMASK; /* M = P - 1 */
TR = ReadTAB (MR); /* T = last word fetched */ TR = ReadTAB (MR); /* T = last word fetched */
saved_MR = MR; /* save for T cmd update */ 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? */ if (reason == STOP_HALT) /* programmed halt? */
cpu_set_ldr (NULL, FALSE, NULL, NULL); /* disable loader (after T is read) */ cpu_set_ldr (NULL, FALSE, NULL, NULL); /* disable loader (after T is read) */
else /* simulation stop */ else /* simulation stop */
PC = err_PC; /* back out instruction */ PR = err_PC; /* back out instruction */
dms_upd_sr (); /* update dms_sr */ dms_upd_sr (); /* update dms_sr */
dms_upd_vr (MR); /* update dms_vr */ dms_upd_vr (MR); /* update dms_vr */
@ -1841,7 +1842,7 @@ uint32 MA;
MA = IR & (I_IA | I_DISP); /* ind + disp */ MA = IR & (I_IA | I_DISP); /* ind + disp */
if (IR & I_CP) /* current page? */ 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 */ 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? */ if (((sop == soSFC) || (sop == soSFS)) && /* testing flag state? */
((IOSIGNAL) iodata == ioSKF)) /* and SKF asserted? */ ((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? */ else if (sop == soLIX) /* LIA/B instruction? */
ABREG [ab] = iodata; /* load returned data */ ABREG [ab] = iodata; /* load returned data */
@ -2047,7 +2048,7 @@ t_bool calc_defer (void)
uint16 IR; uint16 IR;
if (UNIT_CPU_FAMILY == UNIT_FAMILY_21XX) { /* 21xx series? */ 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? */ if (((IR & I_MRG & ~I_AB) != 0000000) && /* is MRG instruction? */
((IR & I_MRG_I) != I_JSB_I) && /* but not JSB,I? */ ((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? */ if (UNIT_CPU_FAMILY == UNIT_FAMILY_1000) { /* 1000 series? */
memset (M, 0, (uint32) MEMSIZE * 2); /* zero allocated memory */ memset (M, 0, (uint32) MEMSIZE * 2); /* zero allocated memory */
MR = 0077777; /* set M register */ MR = 0077777; /* set M register */
PC = 0100000; /* set P register */ PR = 0100000; /* set P register */
} }
else { /* 21xx series */ else { /* 21xx series */
MR = 0; /* clear M register */ MR = 0; /* clear M register */
PC = 0; /* clear P register */ PR = 0; /* clear P register */
} }
break; break;
@ -3987,7 +3988,7 @@ return SCPE_OK;
/* IBL boot ROM copy /* 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 - Copy boot ROM to memory, updating I/O instructions
- Place 2s complement of boot base in last location - Place 2s complement of boot base in last location
- Modify S register as indicated - Modify S register as indicated
@ -4007,7 +4008,7 @@ cpu_set_ldr (NULL, TRUE, NULL, NULL); /* enable loader (ignore
if (dev < 010) /* valid device? */ if (dev < 010) /* valid device? */
return SCPE_ARG; 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 */ for (i = 0; i < IBL_LNT; i++) { /* copy bootstrap */
wd = rom[i]; /* get word */ 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? */ if (((wd & I_NMRMASK) == I_IO) && /* IO instruction? */
((wd & I_DEVMASK) >= 010) && /* dev >= 10? */ ((wd & I_DEVMASK) >= 010) && /* dev >= 10? */
(I_GETIOOP (wd) != soHLT)) /* not a HALT? */ (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 */ 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[PR + IBL_DPC] = (M[PR + IBL_DPC] + (dev - 010)) & DMASK; /* patch DMA ctrl */
M[PC + IBL_END] = (~PC + 1) & DMASK; /* fill in start of boot */ M[PR + IBL_END] = (~PR + 1) & DMASK; /* fill in start of boot */
SR = (SR & sr_clear) | sr_set; /* modify the S register as indicated */ SR = (SR & sr_clear) | sr_set; /* modify the S register as indicated */

View file

@ -1,6 +1,6 @@
/* hp2100_cpu.h: HP 2100 CPU definitions /* 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 Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"), 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 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. 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 24-Dec-14 JDB Added casts for explicit downward conversions
18-Mar-13 JDB Added declarations for the MP abort handler and CPU registers 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 14-Mar-13 MP Changed guard macro name to avoid reserved namespace
@ -273,7 +274,7 @@
#define BR ABREG[1] /* B = reg 1 */ #define BR ABREG[1] /* B = reg 1 */
extern uint16 ABREG[2]; /* A/B regs (use AR/BR) */ 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 SR; /* S register */
extern uint32 MR; /* M register */ extern uint32 MR; /* M register */
extern uint32 TR; /* T register */ extern uint32 TR; /* T register */

View file

@ -1,6 +1,6 @@
/* hp2100_cpu1.c: HP 2100/1000 EAU simulator and UIG dispatcher /* 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 Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"), copy of this software and associated documentation files (the "Software"),
@ -25,6 +25,7 @@
CPU1 Extended arithmetic and optional microcode dispatchers 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 24-Dec-14 JDB Added casts for explicit downward conversions
05-Apr-14 JDB Corrected typo in comments for cpu_ops 05-Apr-14 JDB Corrected typo in comments for cpu_ops
09-May-12 JDB Separated assignments from conditional expressions 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? */ if (UNIT_CPU_MODEL == UNIT_1000_M) /* 1000 M-series? */
goto MPY; /* decode as MPY */ goto MPY; /* decode as MPY */
BR = (BR + 1) & DMASK; /* increment B */ BR = (BR + 1) & DMASK; /* increment B */
if (BR) PC = err_PC; /* if !=0, repeat */ if (BR) PR = err_PC; /* if !=0, repeat */
break; break;
case 004: /* RRL 100100-100117 */ 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 */ flags = pattern & OP_M_FLAGS; /* get operand pattern */
if (flags >= OP_ADR) { /* address operand? */ 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? */ if (reason != SCPE_OK) /* resolution failed? */
return reason; return reason;
} }
@ -765,11 +766,11 @@ for (i = 0; i < OP_N_F; i++) {
break; break;
case OP_CON: /* inline constant operand */ case OP_CON: /* inline constant operand */
*op++ = ReadOp (PC, in_s); /* get value */ *op++ = ReadOp (PR, in_s); /* get value */
break; break;
case OP_VAR: /* inline variable operand */ case OP_VAR: /* inline variable operand */
(*op++).word = (uint16) PC; /* get pointer to variable */ (*op++).word = (uint16) PR; /* get pointer to variable */
break; break;
case OP_ADR: /* inline address operand */ 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? */ 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 */ pattern = pattern >> OP_N_FLAGS; /* move next pattern into place */
} }
return reason; 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 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 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 const char *formats[] = { "%02o", "%06o", "%06o", "%01o", "%06o", "%06o", "%01o", "%06o", "P+%d" };
static char format[20] = " %s = "; /* base format string */ 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 */ ARX = AR; /* copy 16-bit value to static variable */
BRX = BR; /* 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++) { for (i = 0; i < REG_COUNT; i++) {
if (regs & 1) { /* register requested? */ if (regs & 1) { /* register requested? */

View file

@ -1,6 +1,6 @@
/* hp2100_cpu2.c: HP 2100/1000 FP/DMS/EIG/IOP instructions /* 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 Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"), copy of this software and associated documentation files (the "Software"),
@ -26,6 +26,7 @@
CPU2 Floating-point, dynamic mapping, extended, and I/O processor CPU2 Floating-point, dynamic mapping, extended, and I/O processor
instructions instructions
05-Aug-16 JDB Renamed the P register from "PC" to "PR"
24-Dec-14 JDB Added casts for explicit downward conversions 24-Dec-14 JDB Added casts for explicit downward conversions
09-May-12 JDB Separated assignments from conditional expressions 09-May-12 JDB Separated assignments from conditional expressions
11-Sep-08 JDB Moved microcode function prototypes to hp2100_cpu1.h 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; BR = (BR + 1) & DMASK;
XR = (XR - 1) & DMASK; XR = (XR - 1) & DMASK;
if (XR && intrq && !(AR & 1)) { /* more, int, even? */ if (XR && intrq && !(AR & 1)) { /* more, int, even? */
PC = err_PC; /* stop for now */ PR = err_PC; /* stop for now */
break; break;
} }
} }
@ -293,7 +294,7 @@ switch (entry) { /* decode IR<3:0> */
BR = (BR + 1) & DMASK; BR = (BR + 1) & DMASK;
XR = (XR - 1) & DMASK; XR = (XR - 1) & DMASK;
if (XR && intrq && !(AR & 1)) { /* more, int, even? */ if (XR && intrq && !(AR & 1)) { /* more, int, even? */
PC = err_PC; /* stop for now */ PR = err_PC; /* stop for now */
break; break;
} }
} }
@ -309,7 +310,7 @@ switch (entry) { /* decode IR<3:0> */
BR = (BR + 1) & DMASK; BR = (BR + 1) & DMASK;
XR = (XR - 1) & DMASK; XR = (XR - 1) & DMASK;
if (XR && intrq && !(AR & 1)) { /* more, int, even? */ if (XR && intrq && !(AR & 1)) { /* more, int, even? */
PC = err_PC; /* stop for now */ PR = err_PC; /* stop for now */
break; break;
} }
} }
@ -323,7 +324,7 @@ switch (entry) { /* decode IR<3:0> */
BR = (BR + 1) & DMASK; BR = (BR + 1) & DMASK;
XR = (XR - 1) & DMASK; XR = (XR - 1) & DMASK;
if (XR && intrq) { /* more and intr? */ if (XR && intrq) { /* more and intr? */
PC = err_PC; /* stop for now */ PR = err_PC; /* stop for now */
break; break;
} }
} }
@ -337,7 +338,7 @@ switch (entry) { /* decode IR<3:0> */
BR = (BR + 1) & DMASK; BR = (BR + 1) & DMASK;
XR = (XR - 1) & DMASK; XR = (XR - 1) & DMASK;
if (XR && intrq) { /* more and intr? */ if (XR && intrq) { /* more and intr? */
PC = err_PC; /* stop for now */ PR = err_PC; /* stop for now */
break; break;
} }
} }
@ -351,7 +352,7 @@ switch (entry) { /* decode IR<3:0> */
BR = (BR + 1) & DMASK; BR = (BR + 1) & DMASK;
XR = (XR - 1) & DMASK; XR = (XR - 1) & DMASK;
if (XR && intrq) { /* more and intr? */ if (XR && intrq) { /* more and intr? */
PC = err_PC; /* stop for now */ PR = err_PC; /* stop for now */
break; break;
} }
} }
@ -391,8 +392,8 @@ switch (entry) { /* decode IR<3:0> */
if (op[0].word & 0040000) dms_ump = UMAP; /* set/clr usr */ if (op[0].word & 0040000) dms_ump = UMAP; /* set/clr usr */
} }
mp_dms_jmp (op[1].word, 2); /* mpck jmp target */ mp_dms_jmp (op[1].word, 2); /* mpck jmp target */
PCQ_ENTRY; /* save old PC */ PCQ_ENTRY; /* save old P */
PC = op[1].word; /* jump */ PR = op[1].word; /* jump */
ion_defer = 1; /* defer intr */ ion_defer = 1; /* defer intr */
break; break;
@ -416,7 +417,7 @@ switch (entry) { /* decode IR<3:0> */
AR = (AR + 1) & DMASK; AR = (AR + 1) & DMASK;
BR = (BR + 1) & DMASK; BR = (BR + 1) & DMASK;
if (intrq && ((XR & 017) == 017)) { /* intr, grp of 16? */ if (intrq && ((XR & 017) == 017)) { /* intr, grp of 16? */
PC = err_PC; /* stop for now */ PR = err_PC; /* stop for now */
break; break;
} }
} }
@ -431,7 +432,7 @@ switch (entry) { /* decode IR<3:0> */
AR = (AR + 1) & DMASK; AR = (AR + 1) & DMASK;
BR = (BR + 1) & DMASK; BR = (BR + 1) & DMASK;
if (intrq && ((XR & 017) == 017)) { /* intr, grp of 16? */ if (intrq && ((XR & 017) == 017)) { /* intr, grp of 16? */
PC = err_PC; PR = err_PC;
break; break;
} }
} }
@ -459,7 +460,7 @@ switch (entry) { /* decode IR<3:0> */
case 026: /* XCA, XCB 10x726 (OP_A) */ case 026: /* XCA, XCB 10x726 (OP_A) */
if (ABREG[absel] != ReadWA (op[0].word)) /* compare alt */ if (ABREG[absel] != ReadWA (op[0].word)) /* compare alt */
PC = (PC + 1) & VAMASK; PR = (PR + 1) & VAMASK;
break; break;
case 027: /* LFA, LFB 10x727 (OP_N) */ case 027: /* LFA, LFB 10x727 (OP_N) */
@ -481,16 +482,16 @@ switch (entry) { /* decode IR<3:0> */
dms_enb = 0; /* disable map */ dms_enb = 0; /* disable map */
dms_ump = SMAP; dms_ump = SMAP;
mp_dms_jmp (op[0].word, 2); /* validate jump addr */ mp_dms_jmp (op[0].word, 2); /* validate jump addr */
PCQ_ENTRY; /* save curr PC */ PCQ_ENTRY; /* save curr P */
PC = op[0].word; /* new PC */ PR = op[0].word; /* new P */
ion_defer = 1; ion_defer = 1;
break; break;
case 033: /* DJS 105733 (OP_A) */ case 033: /* DJS 105733 (OP_A) */
if (dms_ump) dms_viol (err_PC, MVI_PRV); /* priv viol if prot */ if (dms_ump) dms_viol (err_PC, MVI_PRV); /* priv viol if prot */
WriteW (op[0].word, PC); /* store ret addr */ WriteW (op[0].word, PR); /* store ret addr */
PCQ_ENTRY; /* save curr PC */ PCQ_ENTRY; /* save curr P */
PC = (op[0].word + 1) & VAMASK; /* new PC */ PR = (op[0].word + 1) & VAMASK; /* new P */
dms_enb = 0; /* disable map */ dms_enb = 0; /* disable map */
dms_ump = SMAP; dms_ump = SMAP;
ion_defer = 1; /* defer intr */ ion_defer = 1; /* defer intr */
@ -501,16 +502,16 @@ switch (entry) { /* decode IR<3:0> */
dms_enb = 1; /* enable system */ dms_enb = 1; /* enable system */
dms_ump = SMAP; dms_ump = SMAP;
mp_dms_jmp (op[0].word, 2); /* validate jump addr */ mp_dms_jmp (op[0].word, 2); /* validate jump addr */
PCQ_ENTRY; /* save curr PC */ PCQ_ENTRY; /* save curr P */
PC = op[0].word; /* jump */ PR = op[0].word; /* jump */
ion_defer = 1; /* defer intr */ ion_defer = 1; /* defer intr */
break; break;
case 035: /* SJS 105735 (OP_A) */ case 035: /* SJS 105735 (OP_A) */
if (dms_ump) dms_viol (err_PC, MVI_PRV); /* priv viol if prot */ if (dms_ump) dms_viol (err_PC, MVI_PRV); /* priv viol if prot */
t = PC; /* save retn addr */ t = PR; /* save retn addr */
PCQ_ENTRY; /* save curr PC */ PCQ_ENTRY; /* save curr P */
PC = (op[0].word + 1) & VAMASK; /* new PC */ PR = (op[0].word + 1) & VAMASK; /* new P */
dms_enb = 1; /* enable system */ dms_enb = 1; /* enable system */
dms_ump = SMAP; dms_ump = SMAP;
WriteW (op[0].word, t); /* store ret addr */ WriteW (op[0].word, t); /* store ret addr */
@ -522,16 +523,16 @@ switch (entry) { /* decode IR<3:0> */
dms_enb = 1; /* enable user */ dms_enb = 1; /* enable user */
dms_ump = UMAP; dms_ump = UMAP;
mp_dms_jmp (op[0].word, 2); /* validate jump addr */ mp_dms_jmp (op[0].word, 2); /* validate jump addr */
PCQ_ENTRY; /* save curr PC */ PCQ_ENTRY; /* save curr P */
PC = op[0].word; /* jump */ PR = op[0].word; /* jump */
ion_defer = 1; /* defer intr */ ion_defer = 1; /* defer intr */
break; break;
case 037: /* UJS 105737 (OP_A) */ case 037: /* UJS 105737 (OP_A) */
if (dms_ump) dms_viol (err_PC, MVI_PRV); /* priv viol if prot */ if (dms_ump) dms_viol (err_PC, MVI_PRV); /* priv viol if prot */
t = PC; /* save retn addr */ t = PR; /* save retn addr */
PCQ_ENTRY; /* save curr PC */ PCQ_ENTRY; /* save curr P */
PC = (op[0].word + 1) & VAMASK; /* new PC */ PR = (op[0].word + 1) & VAMASK; /* new P */
dms_enb = 1; /* enable user */ dms_enb = 1; /* enable user */
dms_ump = UMAP; dms_ump = UMAP;
WriteW (op[0].word, t); /* store ret addr */ WriteW (op[0].word, t); /* store ret addr */
@ -710,19 +711,19 @@ switch (entry) { /* decode IR<4:0> */
case 020: /* ISX 105760 (OP_N) */ case 020: /* ISX 105760 (OP_N) */
XR = (XR + 1) & DMASK; /* incr XR */ 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; break;
case 021: /* DSX 105761 (OP_N) */ case 021: /* DSX 105761 (OP_N) */
XR = (XR - 1) & DMASK; /* decr XR */ 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; break;
case 022: /* JLY 105762 (OP_A) */ case 022: /* JLY 105762 (OP_A) */
mp_dms_jmp (op[0].word, 0); /* validate jump addr */ mp_dms_jmp (op[0].word, 0); /* validate jump addr */
PCQ_ENTRY; PCQ_ENTRY;
YR = PC; /* ret addr to YR */ YR = PR; /* ret addr to YR */
PC = op[0].word; /* jump */ PR = op[0].word; /* jump */
break; break;
case 023: /* LBT 105763 (OP_N) */ case 023: /* LBT 105763 (OP_N) */
@ -749,7 +750,7 @@ switch (entry) { /* decode IR<4:0> */
BR = (BR + 1) & DMASK; /* incr dst */ BR = (BR + 1) & DMASK; /* incr dst */
wc = (wc - 1) & DMASK; /* decr cnt */ wc = (wc - 1) & DMASK; /* decr cnt */
if (intrq && wc) { /* intr, more to do? */ if (intrq && wc) { /* intr, more to do? */
PC = err_PC; /* back up PC */ PR = err_PC; /* back up P */
break; break;
} }
} }
@ -764,7 +765,7 @@ switch (entry) { /* decode IR<4:0> */
v1 = ReadB (AR); /* get src1 */ v1 = ReadB (AR); /* get src1 */
v2 = ReadB (BR); /* get src2 */ v2 = ReadB (BR); /* get src2 */
if (v1 != v2) { /* compare */ if (v1 != v2) { /* compare */
PC = (PC + 1 + (v1 > v2)) & VAMASK; PR = (PR + 1 + (v1 > v2)) & VAMASK;
BR = (BR + wc) & DMASK; /* update BR */ BR = (BR + wc) & DMASK; /* update BR */
wc = 0; /* clr interim */ wc = 0; /* clr interim */
break; break;
@ -773,7 +774,7 @@ switch (entry) { /* decode IR<4:0> */
BR = (BR + 1) & DMASK; /* incr src2 */ BR = (BR + 1) & DMASK; /* incr src2 */
wc = (wc - 1) & DMASK; /* decr cnt */ wc = (wc - 1) & DMASK; /* decr cnt */
if (intrq && wc) { /* intr, more to do? */ if (intrq && wc) { /* intr, more to do? */
PC = err_PC; /* back up PC */ PR = err_PC; /* back up P */
break; break;
} }
} }
@ -788,11 +789,11 @@ switch (entry) { /* decode IR<4:0> */
if (t == v1) break; /* test match? */ if (t == v1) break; /* test match? */
BR = (BR + 1) & DMASK; BR = (BR + 1) & DMASK;
if (t == v2) { /* term match? */ if (t == v2) { /* term match? */
PC = (PC + 1) & VAMASK; PR = (PR + 1) & VAMASK;
break; break;
} }
if (intrq) { /* int pending? */ if (intrq) { /* int pending? */
PC = err_PC; /* back up PC */ PR = err_PC; /* back up P */
break; break;
} }
} }
@ -800,19 +801,19 @@ switch (entry) { /* decode IR<4:0> */
case 030: /* ISY 105770 (OP_N) */ case 030: /* ISY 105770 (OP_N) */
YR = (YR + 1) & DMASK; /* incr YR */ 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; break;
case 031: /* DSY 105771 (OP_N) */ case 031: /* DSY 105771 (OP_N) */
YR = (YR - 1) & DMASK; /* decr YR */ 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; break;
case 032: /* JPY 105772 (OP_C) */ case 032: /* JPY 105772 (OP_C) */
op[0].word = (op[0].word + YR) & VAMASK; /* index, no indir */ op[0].word = (op[0].word + YR) & VAMASK; /* index, no indir */
mp_dms_jmp (op[0].word, 0); /* validate jump addr */ mp_dms_jmp (op[0].word, 0); /* validate jump addr */
PCQ_ENTRY; PCQ_ENTRY;
PC = op[0].word; /* jump */ PR = op[0].word; /* jump */
break; break;
case 033: /* SBS 105773 (OP_KA) */ case 033: /* SBS 105773 (OP_KA) */
@ -827,7 +828,7 @@ switch (entry) { /* decode IR<4:0> */
case 035: /* TBS 105775 (OP_KK) */ case 035: /* TBS 105775 (OP_KK) */
if ((op[1].word & op[0].word) != op[0].word) /* test bits */ if ((op[1].word & op[0].word) != op[0].word) /* test bits */
PC = (PC + 1) & VAMASK; PR = (PR + 1) & VAMASK;
break; break;
case 036: /* CMW 105776 (OP_KV) */ case 036: /* CMW 105776 (OP_KV) */
@ -840,7 +841,7 @@ switch (entry) { /* decode IR<4:0> */
sop1 = (int32) SEXT (v1); /* signed */ sop1 = (int32) SEXT (v1); /* signed */
sop2 = (int32) SEXT (v2); sop2 = (int32) SEXT (v2);
if (sop1 != sop2) { /* compare */ if (sop1 != sop2) { /* compare */
PC = (PC + 1 + (sop1 > sop2)) & VAMASK; PR = (PR + 1 + (sop1 > sop2)) & VAMASK;
BR = (BR + wc) & DMASK; /* update BR */ BR = (BR + wc) & DMASK; /* update BR */
wc = 0; /* clr interim */ wc = 0; /* clr interim */
break; break;
@ -849,7 +850,7 @@ switch (entry) { /* decode IR<4:0> */
BR = (BR + 1) & DMASK; /* incr src2 */ BR = (BR + 1) & DMASK; /* incr src2 */
wc = (wc - 1) & DMASK; /* decr cnt */ wc = (wc - 1) & DMASK; /* decr cnt */
if (intrq && wc) { /* intr, more to do? */ if (intrq && wc) { /* intr, more to do? */
PC = err_PC; /* back up PC */ PR = err_PC; /* back up P */
break; break;
} }
} }
@ -870,7 +871,7 @@ switch (entry) { /* decode IR<4:0> */
BR = (BR + 1) & DMASK; /* incr dst */ BR = (BR + 1) & DMASK; /* incr dst */
wc = (wc - 1) & DMASK; /* decr cnt */ wc = (wc - 1) & DMASK; /* decr cnt */
if (intrq && wc) { /* intr, more to do? */ if (intrq && wc) { /* intr, more to do? */
PC = err_PC; /* back up PC */ PR = err_PC; /* back up P */
break; break;
} }
} }
@ -1044,7 +1045,7 @@ switch (entry) { /* decode IR<5:0> */
WriteW ((BR - 1) & VAMASK, 0); /* entry link */ WriteW ((BR - 1) & VAMASK, 0); /* entry link */
WriteW ((tp - 1) & VAMASK, BR); /* tail link */ WriteW ((tp - 1) & VAMASK, BR); /* tail link */
WriteW ((AR + 1) & VAMASK, BR); /* queue tail */ 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; break;
case 005: /* PENQ 105465 (OP_N) */ case 005: /* PENQ 105465 (OP_N) */
@ -1053,7 +1054,7 @@ switch (entry) { /* decode IR<5:0> */
WriteW (AR & VAMASK, BR); /* queue head */ WriteW (AR & VAMASK, BR); /* queue head */
if (hp == 0) /* q empty? */ if (hp == 0) /* q empty? */
WriteW ((AR + 1) & VAMASK, BR); /* queue tail */ WriteW ((AR + 1) & VAMASK, BR); /* queue tail */
else PC = (PC + 1) & VAMASK; /* skip */ else PR = (PR + 1) & VAMASK; /* skip */
break; break;
case 006: /* DEQ 105466 (OP_N) */ case 006: /* DEQ 105466 (OP_N) */
@ -1063,7 +1064,7 @@ switch (entry) { /* decode IR<5:0> */
WriteW (AR & VAMASK, hp); /* becomes queue head */ WriteW (AR & VAMASK, hp); /* becomes queue head */
if (hp == 0) /* q now empty? */ if (hp == 0) /* q now empty? */
WriteW ((AR + 1) & VAMASK, (AR + 1) & DMASK); WriteW ((AR + 1) & VAMASK, (AR + 1) & DMASK);
PC = (PC + 1) & VAMASK; /* skip */ PR = (PR + 1) & VAMASK; /* skip */
} }
break; break;
@ -1078,7 +1079,7 @@ switch (entry) { /* decode IR<5:0> */
wc = (wc - 1) & DMASK; /* decr cnt */ wc = (wc - 1) & DMASK; /* decr cnt */
if (wc && intrq) { /* more and intr? */ if (wc && intrq) { /* more and intr? */
WriteW (op[0].word, wc); /* save count */ WriteW (op[0].word, wc); /* save count */
PC = err_PC; /* stop for now */ PR = err_PC; /* stop for now */
break; break;
} }
} }
@ -1101,7 +1102,7 @@ switch (entry) { /* decode IR<5:0> */
case 012: /* PRFEX 105472 (OP_A) */ case 012: /* PRFEX 105472 (OP_A) */
PCQ_ENTRY; 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 */ WriteW (op[0].word, 0); /* clear exit */
break; break;

View file

@ -1,6 +1,6 @@
/* hp2100_cpu3.c: HP 2100/1000 FFP/DBI instructions /* 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 Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"), copy of this software and associated documentation files (the "Software"),
@ -25,6 +25,7 @@
CPU3 Fast FORTRAN and Double Integer instructions 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 24-Dec-14 JDB Added casts for explicit downward conversions
09-May-12 JDB Separated assignments from conditional expressions 09-May-12 JDB Separated assignments from conditional expressions
11-Sep-08 JDB Moved microcode function prototypes to hp2100_cpu1.h 11-Sep-08 JDB Moved microcode function prototypes to hp2100_cpu1.h
@ -212,7 +213,7 @@ else { /* F-Series */
SR = 0102077; /* test passed code */ SR = 0102077; /* test passed code */
AR = 0; /* test clears A/B */ AR = 0; /* test clears A/B */
BR = 0; 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; return reason;
case 003: /* .DNG 105203 (OP_N) */ case 003: /* .DNG 105203 (OP_N) */
@ -304,7 +305,7 @@ switch (entry) { /* decode IR<4:0> */
return stop_inst; /* trap if not */ return stop_inst; /* trap if not */
if (intrq) { /* interrupt pending? */ if (intrq) { /* interrupt pending? */
PC = err_PC; /* restart instruction */ PR = err_PC; /* restart instruction */
break; break;
} }
@ -317,7 +318,7 @@ switch (entry) { /* decode IR<4:0> */
i = 1; /* params start at op[1] */ i = 1; /* params start at op[1] */
XADD: /* enter here from .XADD */ XADD: /* enter here from .XADD */
if (intrq) { /* interrupt pending? */ if (intrq) { /* interrupt pending? */
PC = err_PC; /* restart instruction */ PR = err_PC; /* restart instruction */
break; break;
} }
@ -329,7 +330,7 @@ switch (entry) { /* decode IR<4:0> */
i = 1; /* params start at op[1] */ i = 1; /* params start at op[1] */
XSUB: /* enter here from .XSUB */ XSUB: /* enter here from .XSUB */
if (intrq) { /* interrupt pending? */ if (intrq) { /* interrupt pending? */
PC = err_PC; /* restart instruction */ PR = err_PC; /* restart instruction */
break; break;
} }
@ -341,7 +342,7 @@ switch (entry) { /* decode IR<4:0> */
i = 1; /* params start at op[1] */ i = 1; /* params start at op[1] */
XMPY: /* enter here from .XMPY */ XMPY: /* enter here from .XMPY */
if (intrq) { /* interrupt pending? */ if (intrq) { /* interrupt pending? */
PC = err_PC; /* restart instruction */ PR = err_PC; /* restart instruction */
break; break;
} }
@ -353,7 +354,7 @@ switch (entry) { /* decode IR<4:0> */
i = 1; /* params start at op[1] */ i = 1; /* params start at op[1] */
XDIV: /* enter here from .XDIV */ XDIV: /* enter here from .XDIV */
if (intrq) { /* interrupt pending? */ if (intrq) { /* interrupt pending? */
PC = err_PC; /* restart instruction */ PR = err_PC; /* restart instruction */
break; break;
} }
@ -383,7 +384,7 @@ switch (entry) { /* decode IR<4:0> */
return stop_inst; /* trap if not */ return stop_inst; /* trap if not */
if (intrq) { /* interrupt pending? */ if (intrq) { /* interrupt pending? */
PC = err_PC; /* restart instruction */ PR = err_PC; /* restart instruction */
break; break;
} }
@ -397,7 +398,7 @@ switch (entry) { /* decode IR<4:0> */
return stop_inst; /* trap if not */ return stop_inst; /* trap if not */
if (intrq) { /* interrupt pending? */ if (intrq) { /* interrupt pending? */
PC = err_PC; /* restart instruction */ PR = err_PC; /* restart instruction */
break; break;
} }
@ -411,7 +412,7 @@ switch (entry) { /* decode IR<4:0> */
case 020: /* .XFER 105220 (OP_N) */ case 020: /* .XFER 105220 (OP_N) */
if (UNIT_CPU_TYPE == UNIT_TYPE_2100) 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 */ XFER: /* enter here from .DFER */
sc = 3; /* set count for 3-wd xfer */ sc = 3; /* set count for 3-wd xfer */
goto CFER; /* do transfer */ goto CFER; /* do transfer */
@ -420,20 +421,20 @@ switch (entry) { /* decode IR<4:0> */
if ((int16) op[1].word < 1) /* index < 1? */ if ((int16) op[1].word < 1) /* index < 1? */
op[1].word = 1; /* reset min */ 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 */ if (sa >= op[0].word) /* must be <= last target */
sa = op[0].word - 1; sa = op[0].word - 1;
da = ReadW (sa); /* get jump target */ da = ReadW (sa); /* get jump target */
reason = resolve (da, &MA, intrq); /* resolve indirects */ reason = resolve (da, &MA, intrq); /* resolve indirects */
if (reason != SCPE_OK) { /* resolution failed? */ if (reason != SCPE_OK) { /* resolution failed? */
PC = err_PC; /* irq restarts instruction */ PR = err_PC; /* irq restarts instruction */
break; break;
} }
mp_dms_jmp (MA, 2); /* validate jump addr */ mp_dms_jmp (MA, 2); /* validate jump addr */
PCQ_ENTRY; /* record last PC */ PCQ_ENTRY; /* record last P */
PC = MA; /* jump */ PR = MA; /* jump */
BR = op[0].word; /* (for 2100 FFP compat) */ BR = op[0].word; /* (for 2100 FFP compat) */
break; break;
@ -446,7 +447,7 @@ switch (entry) { /* decode IR<4:0> */
else { /* 3-dim access */ else { /* 3-dim access */
reason = cpu_ops (OP_KK, op2, intrq); /* get 1st, 2nd ranges */ reason = cpu_ops (OP_KK, op2, intrq); /* get 1st, 2nd ranges */
if (reason != SCPE_OK) { /* evaluation failed? */ if (reason != SCPE_OK) { /* evaluation failed? */
PC = err_PC; /* irq restarts instruction */ PR = err_PC; /* irq restarts instruction */
break; break;
} }
op[1].word = op[1].word + /* offset */ op[1].word = op[1].word + /* offset */
@ -458,7 +459,7 @@ switch (entry) { /* decode IR<4:0> */
break; break;
case 023: /* .ENTR 105223 (OP_A) */ 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 */ ENTR: /* enter here from .ENTP */
da = op[0].word; /* get addr of 1st formal */ da = op[0].word; /* get addr of 1st formal */
dc = MA - da; /* get count of formals */ dc = MA - da; /* get count of formals */
@ -473,7 +474,7 @@ switch (entry) { /* decode IR<4:0> */
MA = ReadW (sa++); /* get addr of actual */ MA = ReadW (sa++); /* get addr of actual */
reason = resolve (MA, &MA, intrq); /* resolve indirect */ reason = resolve (MA, &MA, intrq); /* resolve indirect */
if (reason != SCPE_OK) { /* resolution failed? */ if (reason != SCPE_OK) { /* resolution failed? */
PC = err_PC; /* irq restarts instruction */ PR = err_PC; /* irq restarts instruction */
break; break;
} }
WriteW (da++, MA); /* put addr into formal */ WriteW (da++, MA); /* put addr into formal */
@ -484,7 +485,7 @@ switch (entry) { /* decode IR<4:0> */
break; break;
case 024: /* .ENTP 105224 (OP_A) */ case 024: /* .ENTP 105224 (OP_A) */
MA = PC - 5; /* get addr of entry point */ MA = PR - 5; /* get addr of entry point */
goto ENTR; goto ENTR;
case 025: /* .PWR2 105225 (OP_RK) */ case 025: /* .PWR2 105225 (OP_RK) */
@ -521,7 +522,7 @@ switch (entry) { /* decode IR<4:0> */
if (op[0].word && intrq) { /* more and intr? */ if (op[0].word && intrq) { /* more and intr? */
AR = (uint16) sa; /* restore A */ AR = (uint16) sa; /* restore A */
BR = (uint16) sb; /* restore B */ BR = (uint16) sb; /* restore B */
PC = err_PC; /* restart instruction */ PR = err_PC; /* restart instruction */
break; break;
} }
} }
@ -666,7 +667,7 @@ switch (entry) { /* decode IR<3:0> */
XR = 2; /* set revision */ XR = 2; /* set revision */
BR = 0377; /* side effect of microcode */ BR = 0377; /* side effect of microcode */
SR = 0102077; /* set "pass" code */ 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 */ t = (AR << 16) | BR; /* set t for return */
break; break;
@ -746,9 +747,9 @@ switch (entry) { /* decode IR<3:0> */
case 004: /* .DCO 105324 (OP_JD) */ case 004: /* .DCO 105324 (OP_JD) */
t = op[0].dword; /* copy for later store */ t = op[0].dword; /* copy for later store */
if ((int32) op[0].dword < (int32) op[1].dword) 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) 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 */ break; /* = rtns to P+1 */
case 005: /* .DDI 105325 (OP_JD) */ case 005: /* .DDI 105325 (OP_JD) */
@ -796,7 +797,7 @@ switch (entry) { /* decode IR<3:0> */
t = din.dword = din.dword + 1; /* increment value */ t = din.dword = din.dword + 1; /* increment value */
WriteOp (op[0].word, din, in_d); /* store it back */ WriteOp (op[0].word, din, in_d); /* store it back */
if (t == 0) if (t == 0)
PC = (PC + 1) & VAMASK; /* skip if result zero */ PR = (PR + 1) & VAMASK; /* skip if result zero */
break; break;
case 013: /* .DDS 105333 (OP_A) */ case 013: /* .DDS 105333 (OP_A) */
@ -804,7 +805,7 @@ switch (entry) { /* decode IR<3:0> */
t = din.dword = din.dword - 1; /* decrement value */ t = din.dword = din.dword - 1; /* decrement value */
WriteOp (op[0].word, din, in_d); /* write it back */ WriteOp (op[0].word, din, in_d); /* write it back */
if (t == 0) if (t == 0)
PC = (PC + 1) & VAMASK; /* skip if result zero */ PR = (PR + 1) & VAMASK; /* skip if result zero */
break; break;
case 014: /* .DSBR 105334 (OP_JD) */ case 014: /* .DSBR 105334 (OP_JD) */

View file

@ -1,6 +1,6 @@
/* hp2100_cpu4.c: HP 1000 FPP/SIS /* 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 Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"), copy of this software and associated documentation files (the "Software"),
@ -25,6 +25,7 @@
CPU4 Floating Point Processor and Scientific Instruction Set 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 24-Dec-14 JDB Added casts for explicit downward conversions
09-May-12 JDB Separated assignments from conditional expressions 09-May-12 JDB Separated assignments from conditional expressions
06-Feb-12 JDB Added OPSIZE casts to fp_accum calls in .FPWR/.TPWR 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) */ case 0004: /* [tst] 105004 (OP_N) */
XR = 3; /* firmware revision */ XR = 3; /* firmware revision */
SR = 0102077; /* test passed code */ 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; break;
case 0005: /* [xpd] 105005 (OP_C) */ case 0005: /* [xpd] 105005 (OP_C) */
@ -313,22 +314,22 @@ switch (entry) { /* decode IR<6:0> */
case 0007: /* [stk] 105007 (OP_A) */ case 0007: /* [stk] 105007 (OP_A) */
O = 0; /* clear overflow */ 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 */ rtn_addr = op[0].word; /* save return address */
while (TRUE) { 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; stk_ptr = (stk_ptr + 1) & VAMASK;
reason = cpu_ops (OP_CCACACCA, op, intrq); /* get instruction set */ reason = cpu_ops (OP_CCACACCA, op, intrq); /* get instruction set */
if (reason) { if (reason) {
PC = err_PC; /* irq restarts */ PR = err_PC; /* irq restarts */
break; break;
} }
if (op[0].word == 0) { /* opcode = NOP? */ 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 */ break; /* done */
} }
@ -336,7 +337,7 @@ switch (entry) { /* decode IR<6:0> */
&op1_prec, &op2_prec, &rslt_prec); &op1_prec, &op2_prec, &rslt_prec);
if (TO_COUNT(op1_prec) != op[1].word) { /* first operand precisions agree? */ 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; break;
} }
@ -344,7 +345,7 @@ switch (entry) { /* decode IR<6:0> */
op[1] = ReadOp (op[2].word, op1_prec); /* no, so get operand 1 */ 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? */ 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; break;
} }
@ -633,7 +634,7 @@ switch (entry) { /* decode IR<3:0> */
if (multiple & 0002) /* multiple * 2 odd? */ if (multiple & 0002) /* multiple * 2 odd? */
fp_exec (0064, &op[0], minus_1, NOP); /* res = -1.0 / acc */ 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; break;
@ -641,7 +642,7 @@ switch (entry) { /* decode IR<3:0> */
O = 0; /* clear overflow */ O = 0; /* clear overflow */
if (op[0].fpk[0] == 0) { /* arg = 0? */ 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; break;
} }
@ -688,7 +689,7 @@ switch (entry) { /* decode IR<3:0> */
fp_pack (&op[0], op[1], exponent, fp_f);/* repack result */ 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; break;
@ -728,7 +729,7 @@ switch (entry) { /* decode IR<3:0> */
if (entry == 007) /* ALOGT? */ if (entry == 007) /* ALOGT? */
fp_exec (0050, &op[0], NOP, log_e); /* res = acc * log(e) */ 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; break;
@ -812,7 +813,7 @@ switch (entry) { /* decode IR<3:0> */
if (multiple & 0002) /* multiple * 2 odd? */ if (multiple & 0002) /* multiple * 2 odd? */
fp_pcom (&op[0], fp_f); /* make negative */ 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; break;
@ -833,7 +834,7 @@ switch (entry) { /* decode IR<3:0> */
op[0].fpk[0] = 0; /* result is zero */ op[0].fpk[0] = 0; /* result is zero */
op[0].fpk[1] = 0; op[0].fpk[1] = 0;
O = 0; /* clear for underflow */ O = 0; /* clear for underflow */
PC = (PC + 1) & VAMASK; /* normal return is P+2 */ PR = (PR + 1) & VAMASK; /* normal return is P+2 */
break; 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; break;
@ -896,7 +897,7 @@ switch (entry) { /* decode IR<3:0> */
else { /* 0.5 <= abs (arg) < 8.0 */ else { /* 0.5 <= abs (arg) < 8.0 */
BR = BR + 2; /* arg = arg * 2.0 */ BR = BR + 2; /* arg = arg * 2.0 */
cpu_sis (0105326, intrq); /* calc exp (arg) */ 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[0] = AR; /* save value */
op[0].fpk[1] = BR; 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? */ if ((f < 0) || (f == 2) || (f == 6) || /* EXP, TANH, or COS? */
(exponent - rsltexp < 5)) { /* bits lost < 5? */ (exponent - rsltexp < 5)) { /* bits lost < 5? */
WriteOp (op[0].word, result, fp_t); /* write result */ 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 */ op[0].fpk[1] = BR; /* return LSBs of N in B */
break; /* all done! */ 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) */ fp_exec (0012, &result, NOP, op[5]); /* result = acc + (x - xu) * c + (cu * xu - n) */
WriteOp (op[0].word, result, fp_t); /* write result */ 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 */ op[0].fpk[1] = BR; /* return LSBs of N in B */
break; break;
@ -1112,7 +1113,7 @@ switch (entry) { /* decode IR<3:0> */
case 017: /* [tst] 105337 (OP_N) */ case 017: /* [tst] 105337 (OP_N) */
XR = 4; /* firmware revision */ XR = 4; /* firmware revision */
SR = 0102077; /* test passed code */ 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; return reason;

View file

@ -1,7 +1,7 @@
/* hp2100_cpu5.c: HP 1000 RTE-6/VM VMA and RTE-IV EMA instructions /* hp2100_cpu5.c: HP 1000 RTE-6/VM VMA and RTE-IV EMA instructions
Copyright (c) 2007-2008, Holger Veit 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 Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"), copy of this software and associated documentation files (the "Software"),
@ -26,6 +26,7 @@
CPU5 RTE-6/VM and RTE-IV firmware option instructions 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 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 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 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 */ eqt = ReadIO(xeqt,UMAP); /* get ID segment */
mls = ReadIO(eqt+33,SMAP); /* get word33 of alternate map */ mls = ReadIO(eqt+33,SMAP); /* get word33 of alternate map */
if ((mls & 0x8000) == 0) { /* this is not an MLS prog! */ if ((mls & 0x8000) == 0) { /* this is not an MLS prog! */
PC = err_PC; PR = err_PC;
if (debug) 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 */ if (mp_control) MP_ABORT (eqt+33); /* allow an MP abort */
return STOP_HALT; /* FATAL error! */ return STOP_HALT; /* FATAL error! */
} }
pnod = mls & 01777; /* get #pages of mem res nodes */ pnod = mls & 01777; /* get #pages of mem res nodes */
if (pnod == 0) { /* no pages? FATAL! */ if (pnod == 0) { /* no pages? FATAL! */
PC = err_PC; PR = err_PC;
if (debug) 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 */ if (mp_control) MP_ABORT (eqt+33); /* allow an MP abort */
return STOP_HALT; return STOP_HALT;
} }
@ -213,20 +214,20 @@ lgpg = op[0].word;
/* lets do some consistency checks, CPU halt if they fail */ /* lets do some consistency checks, CPU halt if they fail */
if (lstpg < lgpg || lgpg < fstpg) { /* assert LSTPG >= LGPG# >= FSTPG */ if (lstpg < lgpg || lgpg < fstpg) { /* assert LSTPG >= LGPG# >= FSTPG */
PC = err_PC; PR = err_PC;
if (debug) if (debug)
fprintf(sim_deb, 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 */ if (mp_control) MP_ABORT (eqt+22); /* allow an MP abort */
return STOP_HALT; return STOP_HALT;
} }
relpg = op[1].word; relpg = op[1].word;
if (pnod < relpg || relpg < (rotsz+1)) { /* assert #PNOD >= RELPG >= ROTSZ+1 */ if (pnod < relpg || relpg < (rotsz+1)) { /* assert #PNOD >= RELPG >= ROTSZ+1 */
PC = err_PC; PR = err_PC;
if (debug) if (debug)
fprintf(sim_deb, 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 */ if (mp_control) MP_ABORT (eqt+22); /* allow an MP abort */
return STOP_HALT; return STOP_HALT;
} }
@ -234,10 +235,10 @@ if (pnod < relpg || relpg < (rotsz+1)) { /* assert #PNOD >= RELPG >=
relbp = op[2].word; relbp = op[2].word;
if (relbp != 0) /* assert RELBP == 0 OR */ if (relbp != 0) /* assert RELBP == 0 OR */
if (pnod < relbp || relbp < (rotsz+1)) { /* #PNOD >= RELBP >= ROTSZ+1 */ if (pnod < relbp || relbp < (rotsz+1)) { /* #PNOD >= RELBP >= ROTSZ+1 */
PC = err_PC; PR = err_PC;
if (debug) if (debug)
fprintf(sim_deb, 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 */ if (mp_control) MP_ABORT (eqt+22); /* allow an MP abort */
return STOP_HALT; return STOP_HALT;
} }
@ -266,13 +267,13 @@ while (cnt != 0) {
dms_wmap(32,relbp+ptnpg); /* map base page again */ dms_wmap(32,relbp+ptnpg); /* map base page again */
WriteW(op[3].word,op[4].word); /* path# we are going to */ 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. */ /* 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 */ /* so must skip back to the original call */
/* which will now lead to the real routine */ /* which will now lead to the real routine */
if (debug) 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; return SCPE_OK;
} }
@ -314,7 +315,7 @@ if (ReadIO(ema+1,UMAP) != 0104400) {
return STOP_HALT; /* FATAL: no EMA/VMA! */ 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 */ /* will return to fault instruction */
AR = (ptr >> 16) & DMASK; /* restore A, B */ AR = (ptr >> 16) & DMASK; /* restore A, B */
@ -323,7 +324,7 @@ E = 0; /* enforce E = 0 */
if (debug) if (debug)
fprintf(sim_deb, fprintf(sim_deb,
">>CPU VMA: Call pg fault OS exit, AR=%06o BR=%06o P=%06o\n", ">>CPU VMA: Call pg fault OS exit, AR=%06o BR=%06o P=%06o\n",
AR, BR, PC); AR, BR, PR);
return SCPE_OK; return SCPE_OK;
} }
@ -489,7 +490,7 @@ if (mapnm > 31) { /* check for invalid map reg
AR = 80; /* error: corrupt EMA/VMA system */ AR = 80; /* error: corrupt EMA/VMA system */
if (debug) if (debug)
fprintf(sim_deb, ">>CPU VMA: .PMAP invalid mapr: AR=80, exit P+1\n"); 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 */ 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, fprintf(sim_deb,
">>CPU VMA: .PMAP pg fault&bit15: XR=%06o YR=%06o, exit P+1\n", ">>CPU VMA: .PMAP pg fault&bit15: XR=%06o YR=%06o, exit P+1\n",
XR, YR); 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] */ /* PTE is successfully mapped to page31 and dmsmap[63] */
@ -515,9 +516,9 @@ if (!cpu_vma_ptevl(pagid,&physpg)) {
fprintf(sim_deb, fprintf(sim_deb,
">>CPU VMA: .PMAP pg map&bit15: XR=%06o YR=%06o, exit P+1\n", ">>CPU VMA: .PMAP pg map&bit15: XR=%06o YR=%06o, exit P+1\n",
XR, YR); 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; E = 1;
@ -532,7 +533,7 @@ if (mapnm != 31) /* unless already unmapped,
AR = (umapr + 1) & DMASK; /* increment mapr for next call */ AR = (umapr + 1) & DMASK; /* increment mapr for next call */
BR = (pagid + 1) & DMASK; /* increment pagid for next call */ BR = (pagid + 1) & DMASK; /* increment pagid for next call */
O = 0; /* clear overflow */ O = 0; /* clear overflow */
PC = (PC + 1) & VAMASK; /* normal PC+2 return */ PR = (PR + 1) & VAMASK; /* normal P+2 return */
if (debug) if (debug)
fprintf(sim_deb,">>CPU VMA: .PMAP map done: AR=%06o BR=%o6o exit P+2\n",AR,BR); fprintf(sim_deb,">>CPU VMA: .PMAP map done: AR=%06o BR=%o6o exit P+2\n",AR,BR);
return SCPE_OK; return SCPE_OK;
@ -656,7 +657,7 @@ uint16 t16;
uint32 entry,t32,ndim; uint32 entry,t32,ndim;
uint32 dtbl,atbl; /* descriptor table ptr, actual args ptr */ uint32 dtbl,atbl; /* descriptor table ptr, actual args ptr */
OP dop0,dop1; 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); t_bool debug = DEBUG_PRI (cpu_dev, DEB_VMA);
entry = IR & 017; /* mask to entry point */ 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 */ XR = 3; /* refer to src code 92084-18828 rev 3 */
SR = 0102077; /* HLT 77 instruction */ SR = 0102077; /* HLT 77 instruction */
YR = 1; /* ROMs correctly installed */ 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; break;
case 003: /* [swap] 105243 (OP_N) */ case 003: /* [swap] 105243 (OP_N) */
@ -723,16 +724,16 @@ switch (entry) { /* decode IR<3:0> */
case 010: /* .IMAP 105250 (OP_A) */ case 010: /* .IMAP 105250 (OP_A) */
dtbl = op[0].word; 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 */ reason = cpu_vma_ijmar(in_s,dtbl,atbl,&ndim,intrq,debug); /* calc the virt address to AB */
if (reason) if (reason)
return reason; return reason;
t32 = (AR << 16) | (BR & DMASK); 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) if (reason)
return reason; return reason;
if (PC==pcsave) if (PR==pcsave)
PC = (PC+ndim) & VAMASK; /* adjust PC: skip ndim subscript words */ PR = (PR+ndim) & VAMASK; /* adjust P: skip ndim subscript words */
break; break;
case 011: /* .IMAR 105251 (OP_A) */ case 011: /* .IMAR 105251 (OP_A) */
@ -743,16 +744,16 @@ switch (entry) { /* decode IR<3:0> */
case 012: /* .JMAP 105252 (OP_A) */ case 012: /* .JMAP 105252 (OP_A) */
dtbl = op[0].word; 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 */ reason = cpu_vma_ijmar(in_d,dtbl,atbl,&ndim,intrq,debug); /* calc the virtual address to AB */
if (reason) if (reason)
return reason; return reason;
t32 = (AR << 16) | (BR & DMASK); 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) if (reason)
return reason; return reason;
if (PC==pcsave) if (PR==pcsave)
PC = (PC + ndim) & VAMASK; /* adjust PC: skip ndim subscript dword ptr */ PR = (PR + ndim) & VAMASK; /* adjust P: skip ndim subscript dword ptr */
break; break;
case 013: /* .JMAR 105253 (OP_A) */ 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 */ dop0 = ReadOp(op[0].word,in_d); /* get pointer from arg */
dop1 = ReadOp(op[1].word,in_d); dop1 = ReadOp(op[1].word,in_d);
t32 = dop0.dword + dop1.dword; /* add offset to it */ 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; break;
case 015: /* .LPX 105255 (OP_A) */ case 015: /* .LPX 105255 (OP_A) */
t32 = (AR << 16) | (BR & DMASK); /* pointer in AB */ t32 = (AR << 16) | (BR & DMASK); /* pointer in AB */
dop0 = ReadOp(op[0].word,in_d); 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; break;
case 016: /* .LBPR 105256 (OP_A) */ case 016: /* .LBPR 105256 (OP_A) */
dop0 = ReadOp(op[0].word,in_d); /* get the pointer */ 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; break;
case 017: /* .LBP 105257 (OP_N) */ case 017: /* .LBP 105257 (OP_N) */
t32 = (AR << 16) | (BR & DMASK); 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; break;
} }
@ -1386,7 +1387,7 @@ if (pattern != OP_N) {
} }
if (debug) { /* debugging? */ 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 */ fprint_sym (sim_deb, err_PC, (t_value *) &IR, /* print instruction mnemonic */
NULL, SWMASK('M')); NULL, SWMASK('M'));
fputc (')', sim_deb); fputc (')', sim_deb);
@ -1399,11 +1400,11 @@ switch (entry) { /* decode IR<3:0> */
case 000: /* .EMIO 105240 (OP_A) */ case 000: /* .EMIO 105240 (OP_A) */
rtn = op[0].word; rtn = op[0].word;
reason = cpu_ema_emio(&rtn, op[1].word, reason = cpu_ema_emio(&rtn, op[1].word,
op[2].word, PC, debug); /* handle the EMIO instruction */ op[2].word, PR, debug); /* handle the EMIO instruction */
PC = rtn; PR = rtn;
if (debug) if (debug)
fprintf (sim_deb, ">>CPU EMA: return .EMIO: AR = %06o, BR = %06o, rtn=%s\n", 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; break;
case 001: /* .MMAP 105241 (OP_AKK) */ case 001: /* .MMAP 105241 (OP_AKK) */
@ -1426,11 +1427,11 @@ switch (entry) { /* decode IR<3:0> */
case 017: /* .EMAP 105247 (OP_A) */ case 017: /* .EMAP 105247 (OP_A) */
rtn = op[0].word; /* error return */ rtn = op[0].word; /* error return */
reason = cpu_ema_emap(&rtn, op[1].word, reason = cpu_ema_emap(&rtn, op[1].word,
op[2].word, PC, debug); /* handle the EMAP instruction */ op[2].word, PR, debug); /* handle the EMAP instruction */
PC = rtn; PR = rtn;
if (debug) { if (debug) {
fprintf (sim_deb, ">>CPU EMA: return .EMAP: AR = %06o, BR = %06o, rtn=%s\n", 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; break;

View file

@ -25,6 +25,7 @@
CPU6 RTE-6/VM OS instructions 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 17-May-16 JDB Set local variable instead of call parameter for .SIP test
24-Dec-14 JDB Added casts for explicit downward conversions 24-Dec-14 JDB Added casts for explicit downward conversions
18-Mar-13 JDB Use MP abort handler declaration in hp2100_cpu.h 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 */ 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 + 1, AR); /* save A */
WriteW (save_area + 2, BR); /* save B */ WriteW (save_area + 2, BR); /* save B */
WriteW (save_area + 3, (E << 15) & SIGN | O & 1); /* save E and O */ 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) static t_stat cpu_save_state (uint32 iotrap)
{ {
uint16 vectors; uint16 vectors;
uint32 saved_PC, int_sys_off; uint32 saved_PR, int_sys_off;
t_stat reason; 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 */ reason = iogrp (SFS_0_C, iotrap); /* turn interrupt system off */
int_sys_off = (PC == saved_PC); /* set flag if already off */ int_sys_off = (PR == saved_PR); /* set flag if already off */
PC = saved_PC; /* restore PC in case it bumped */ PR = saved_PR; /* restore P in case it bumped */
vectors = ReadW (vctr); /* get address of vectors (in SMAP) */ 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 */ dms_ump = SMAP; /* set system map */
vectors = ReadW (vctr); /* get address of vectors (in SMAP) */ 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 */ else { /* privileged call */
@ -444,9 +445,9 @@ switch (entry) { /* decode IR<3:0> */
save_area = ReadW (xsusp); /* get addr of P save area */ save_area = ReadW (xsusp); /* get addr of P save area */
if (dms_ump) /* user map current? */ 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 */ 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 */ WriteW (pvcn, (ReadW (pvcn) + 1) & DMASK); /* increment priv nest counter */
@ -454,7 +455,7 @@ switch (entry) { /* decode IR<3:0> */
break; break;
case 001: /* $LIBX 105341 (OP_A) */ 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 */ count = (ReadW (pvcn) - 1) & DMASK; /* decrement priv nest counter */
WriteW (pvcn, count); /* write it back */ WriteW (pvcn, count); /* write it back */
@ -462,7 +463,7 @@ switch (entry) { /* decode IR<3:0> */
dms_ump = SMAP; /* set system map */ dms_ump = SMAP; /* set system map */
reason = cpu_save_regs (iotrap); /* save registers */ reason = cpu_save_regs (iotrap); /* save registers */
vectors = ReadW (vctr); /* get address of vectors */ 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; break;
@ -485,7 +486,7 @@ switch (entry) { /* decode IR<3:0> */
} while ((BR > 0) && (eqt != 0)); /* loop until timeout or done */ } while ((BR > 0) && (eqt != 0)); /* loop until timeout or done */
if (BR == 0) /* which termination condition? */ 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? */ if (debug_print) /* debugging? */
fprint_regs ("; result:", /* print return registers */ 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] */ AR = (key + 15) & DMASK; /* A = addr of IDSEG [15] */
BR = key; /* B = addr of IDSEG [0] */ BR = key; /* B = addr of IDSEG [0] */
E = (uint32) ((test[5] >> 4) & 1); /* E = short ID segment bit */ 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; break;
} }
@ -537,24 +538,24 @@ switch (entry) { /* decode IR<3:0> */
break; break;
case 004: /* .STIO 105344 (OP_A) */ 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? */ if (debug_print) /* debugging? */
fprintf (sim_deb, /* print registers on entry */ fprintf (sim_deb, /* print registers on entry */
", A = %06o, count = %d", AR, count); ", A = %06o, count = %d", AR, count);
for (i = 0; i < count; i++) { 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 */ reason = resolve (ma, &ma, intrq); /* resolve indirect */
if (reason != SCPE_OK) { /* resolution failed? */ if (reason != SCPE_OK) { /* resolution failed? */
PC = err_PC; /* IRQ restarts instruction */ PR = err_PC; /* IRQ restarts instruction */
break; break;
} }
WriteW (ma, ReadW (ma) & ~I_DEVMASK | AR); /* set SC into instruction */ 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; break;
@ -566,7 +567,7 @@ switch (entry) { /* decode IR<3:0> */
key = ReadW (BR); /* read a buffer word */ key = ReadW (BR); /* read a buffer word */
if (key == AR) { /* does it match? */ if (key == AR) { /* does it match? */
PC = (PC + 1) & VAMASK; /* P+1 found return */ PR = (PR + 1) & VAMASK; /* P+1 found return */
break; break;
} }
@ -633,9 +634,9 @@ switch (entry) { /* decode IR<3:0> */
} }
if (AR == 0) /* exhausted list? */ 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? */ 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 */ /* P+0 bad link */
if (debug_print) /* debugging? */ if (debug_print) /* debugging? */
fprint_regs ("; result:", /* print return registers */ 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 */ reason = iogrp (CLF_0, iotrap); /* turn interrupt system off */
if (irq) /* was interrupt pending? */ 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 */ /* P+0 return for no pending IRQ */
if (debug_print) /* debugging? */ if (debug_print) /* debugging? */
fprintf (sim_deb, /* print return registers */ fprintf (sim_deb, /* print return registers */
", CIR = %02o, return = P+%d", ", CIR = %02o, return = P+%d",
irq, PC - (err_PC + 1)); irq, PR - (err_PC + 1));
break; break;
case 011: /* .YLD 105351 (OP_C) */ 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 */ reason = iogrp (STF_0, iotrap); /* turn interrupt system on */
ion_defer = 0; /* kill defer so irq occurs immed */ ion_defer = 0; /* kill defer so irq occurs immed */
break; break;
case 012: /* .CPM 105352 (OP_KK) */ case 012: /* .CPM 105352 (OP_KK) */
if (INT16 (op[0].word) > INT16 (op[1].word)) 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)) 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 */ /* P+0 arg1 = arg2 */
if (debug_print) /* debugging? */ if (debug_print) /* debugging? */
fprint_regs (",", REG_P_REL, err_PC + 3); /* print return registers */ fprint_regs (",", REG_P_REL, err_PC + 3); /* print return registers */
@ -698,7 +699,7 @@ switch (entry) { /* decode IR<3:0> */
} }
else { /* .ENTN instruction */ 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 */ ENTX: /* enter here from .ENTC */
reason = cpu_ops (OP_A, op, intrq); /* get instruction operand */ 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 */ reason = resolve (ma, &ma, intrq); /* resolve indirect */
if (reason != SCPE_OK) { /* resolution failed? */ if (reason != SCPE_OK) { /* resolution failed? */
PC = err_PC; /* irq restarts instruction */ PR = err_PC; /* irq restarts instruction */
break; break;
} }
@ -738,13 +739,13 @@ switch (entry) { /* decode IR<3:0> */
vectors = ReadW (vctr); /* get address of vectors (in SMAP) */ vectors = ReadW (vctr); /* get address of vectors (in SMAP) */
if (mp_viol & SIGN) { /* parity error? */ if (mp_viol & SIGN) { /* parity error? */
WriteW (vectors + cic_offset, PC); /* save point of suspension in $CIC */ WriteW (vectors + cic_offset, PR); /* save point of suspension in $CIC */
PC = ReadW (vectors + perr_offset); /* vector to $PERR for processing */ PR = ReadW (vectors + perr_offset); /* vector to $PERR for processing */
} }
else { /* MP/DMS violation */ else { /* MP/DMS violation */
cpu_save_regs (iotrap); /* save CPU registers */ 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? */ if (debug_print) { /* debugging? */
@ -763,7 +764,7 @@ switch (entry) { /* decode IR<3:0> */
YR = 0000000; /* RPL switch (not implemented) */ YR = 0000000; /* RPL switch (not implemented) */
AR = 0000000; /* LDR [B] (not implemented) */ AR = 0000000; /* LDR [B] (not implemented) */
SR = 0102077; /* test passed code */ 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, */ if ((cpu_dev.dctrl & DEB_OS) && /* OS debug flag set, */
(sim_deb == NULL)) /* but debugging disabled? */ (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) */ vectors = ReadW (vctr); /* get address of vectors (in SMAP) */
if (INT16 (AR) < 0) /* negative (program ID)? */ 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)? */ 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) */ 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? */ if (debug_print) /* debugging? */
fprintf (sim_deb, /* print return registers */ fprintf (sim_deb, /* print return registers */
@ -799,7 +800,7 @@ switch (entry) { /* decode IR<3:0> */
} }
else { /* .ENTC instruction */ 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 */ goto ENTX; /* continue with common processing */
} }
break; break;
@ -808,7 +809,7 @@ switch (entry) { /* decode IR<3:0> */
if (iotrap) { /* in trap cell? */ if (iotrap) { /* in trap cell? */
reason = cpu_save_state (iotrap); /* TBG interrupt */ reason = cpu_save_state (iotrap); /* TBG interrupt */
vectors = ReadW (vctr); /* get address of vectors (in SMAP) */ 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? */ if (debug_print) /* debugging? */
fprint_regs (",", REG_CIR, 0); /* print interrupt source */ fprint_regs (",", REG_CIR, 0); /* print interrupt source */

View file

@ -1,7 +1,7 @@
/* hp2100_cpu7.c: HP 1000 VIS and SIGNAL/1000 microcode /* hp2100_cpu7.c: HP 1000 VIS and SIGNAL/1000 microcode
Copyright (c) 2008, Holger Veit 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 Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"), copy of this software and associated documentation files (the "Software"),
@ -26,6 +26,7 @@
CPU7 Vector Instruction Set and SIGNAL firmware 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 24-Dec-14 JDB Added casts for explicit downward conversions
18-Mar-13 JDB Moved EMA helper declarations to hp2100_cpu1.h 18-Mar-13 JDB Moved EMA helper declarations to hp2100_cpu1.h
09-May-12 JDB Separated assignments from conditional expressions 09-May-12 JDB Separated assignments from conditional expressions
@ -375,19 +376,19 @@ entry = IR & 017; /* mask to entry point
pattern = op_vis[entry]; pattern = op_vis[entry];
if (entry==0) { /* retrieve sub opcode */ if (entry==0) { /* retrieve sub opcode */
ret = ReadOp (PC, in_s); /* get it */ ret = ReadOp (PR, in_s); /* get it */
subcode = ret.word; subcode = ret.word;
if (subcode & 0100000) /* special property of ucode */ if (subcode & 0100000) /* special property of ucode */
subcode = AR; /* for reentry */ 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 */ pattern = (subcode & 0400) ? OP_AAKAKK : OP_AKAKAKK; /* scalar or vector operation */
} }
if (pattern != OP_N) { if (pattern != OP_N) {
if (op_ftnret[entry]) { /* most VIS instrs ignore RTN addr */ 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 */ 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 */ reason = cpu_ops (pattern, op, intrq); /* get instruction operands */
if (reason != SCPE_OK) /* evaluation failed? */ if (reason != SCPE_OK) /* evaluation failed? */
@ -445,17 +446,17 @@ switch (entry) { /* decode IR<3:0> */
vis_movswp(op,opsize,TRUE); vis_movswp(op,opsize,TRUE);
break; break;
case 014: /* .ERES (OP_(A)AA) */ case 014: /* .ERES (OP_(A)AA) */
reason = cpu_ema_eres(&rtn,op[2].word,PC,debug); /* handle the ERES instruction */ reason = cpu_ema_eres(&rtn,op[2].word,PR,debug); /* handle the ERES instruction */
PC = rtn; PR = rtn;
if (debug) if (debug)
fprintf (sim_deb, fprintf (sim_deb,
">>CPU VIS: return .ERES: AR = %06o, BR = %06o, rtn=%s\n", ">>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; break;
case 015: /* .ESEG (OP_(A)A) */ case 015: /* .ESEG (OP_(A)A) */
reason = cpu_ema_eseg(&rtn,IR,op[0].word,debug); /* handle the ESEG instruction */ reason = cpu_ema_eseg(&rtn,IR,op[0].word,debug); /* handle the ESEG instruction */
PC = rtn; PR = rtn;
if (debug) if (debug)
fprintf (sim_deb, fprintf (sim_deb,
">>CPU VIS: return .ESEG: AR = %06o , BR = %06o, rtn=%s\n", ">>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) */ case 016: /* .VSET (OP_(A)AAACCC) */
reason = cpu_ema_vset(&rtn,op,debug); reason = cpu_ema_vset(&rtn,op,debug);
PC = rtn; PR = rtn;
if (debug) if (debug)
fprintf (sim_deb, ">>CPU VIS: return .VSET: AR = %06o BR = %06o, rtn=%s\n", fprintf (sim_deb, ">>CPU VIS: return .VSET: AR = %06o BR = %06o, rtn=%s\n",
AR, BR, AR, BR,
@ -474,7 +475,7 @@ switch (entry) { /* decode IR<3:0> */
case 017: /* [test] (OP_N) */ case 017: /* [test] (OP_N) */
XR = 3; /* firmware revision */ XR = 3; /* firmware revision */
SR = 0102077; /* test passed code */ 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; break;
default: /* others undefined */ default: /* others undefined */
reason = stop_inst; 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: * 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 */ * 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); 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; break;
case 001: /* BTRFY (OP_AAFFKK) */ case 001: /* BTRFY (OP_AAFFKK) */
@ -695,7 +696,7 @@ switch (entry) { /* decode IR<3:0> */
sig_btrfy(op[1].word, op[1].word+2, sig_btrfy(op[1].word, op[1].word+2,
op[2], op[3], op[2], op[3],
2*(op[4].word-1), 2*op[5].word); 2*(op[4].word-1), 2*op[5].word);
PC = op[0].word & VAMASK; PR = op[0].word & VAMASK;
break; break;
case 002: /* UNSCR (OP_AAFFKK) */ case 002: /* UNSCR (OP_AAFFKK) */
@ -729,7 +730,7 @@ switch (entry) { /* decode IR<3:0> */
WriteOp(RE(v + idx2), p1, fp_f); WriteOp(RE(v + idx2), p1, fp_f);
(void)fp_exec(020, &p2, d, m2); /* VI[idx2] := 0.5*(p3-p4) - imag(W*(c,d)) */ (void)fp_exec(020, &p2, d, m2); /* VI[idx2] := 0.5*(p3-p4) - imag(W*(c,d)) */
WriteOp(IM(v + idx2), p2, fp_f); WriteOp(IM(v + idx2), p2, fp_f);
PC = op[0].word & VAMASK; PR = op[0].word & VAMASK;
break; break;
case 003: /* PRSCR (OP_AAFFKK) */ case 003: /* PRSCR (OP_AAFFKK) */
@ -763,7 +764,7 @@ switch (entry) { /* decode IR<3:0> */
WriteOp(RE(v + idx2), p1, fp_f); WriteOp(RE(v + idx2), p1, fp_f);
(void)fp_exec(020, &p2, m1, d); /* VI[idx2] := imag(W*(c,d)) - (p3-p4) */ (void)fp_exec(020, &p2, m1, d); /* VI[idx2] := imag(W*(c,d)) - (p3-p4) */
WriteOp(IM(v + idx2), p2, fp_f); WriteOp(IM(v + idx2), p2, fp_f);
PC = op[0].word & VAMASK; PR = op[0].word & VAMASK;
break; break;
case 004: /* BITR1 (OP_AAAKK) */ 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 * difference to BITRV is that BITRV uses complex*8, and BITR1 uses separate real*4
* vectors for Real and Imag parts */ * vectors for Real and Imag parts */
sig_bitrev(op[1].word, op[2].word, op[3].word-1, op[4].word, 2); 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; break;
@ -799,7 +800,7 @@ switch (entry) { /* decode IR<3:0> */
sig_btrfy(op[1].word, op[2].word, sig_btrfy(op[1].word, op[2].word,
op[3], op[4], op[3], op[4],
op[5].word-1, op[6].word); op[5].word-1, op[6].word);
PC = op[0].word & VAMASK; PR = op[0].word & VAMASK;
break; break;
case 006: /* .CADD (OP_AAA) */ case 006: /* .CADD (OP_AAA) */
@ -928,7 +929,7 @@ switch (entry) { /* decode IR<3:0> */
case 017: /* [slftst] (OP_N) */ case 017: /* [slftst] (OP_N) */
XR = 2; /* firmware revision */ XR = 2; /* firmware revision */
SR = 0102077; /* test passed code */ 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; break;
case 016: /* invalid */ case 016: /* invalid */

View file

@ -23,8 +23,9 @@
be used in advertising or otherwise to promote the sale, use or other dealings 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. 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 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 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 28-Dec-14 JDB Changed suppression from #pragma GCC to #pragma clang
05-Feb-13 JDB Added declaration for hp_fprint_stopped 05-Feb-13 JDB Added declaration for hp_fprint_stopped
@ -84,10 +85,6 @@
#include "sim_defs.h" #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 /* 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 not be, in my opinion. They warn about the use of perfectly valid code and

View file

@ -26,6 +26,7 @@
DR 12606B 2770/2771 fixed head disk DR 12606B 2770/2771 fixed head disk
12610B 2773/2774/2775 drum 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 13-May-16 JDB Modified for revised SCP API function parameter types
30-Dec-14 JDB Added S-register parameters to ibl_copy 30-Dec-14 JDB Added S-register parameters to ibl_copy
24-Dec-14 JDB Added casts for explicit downward conversions 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 */ 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 */ return SCPE_IERR; /* return an internal error if the copy failed */
WritePW (PC + IBL_DPC, dr_rom [IBL_DPC]); /* restore overwritten word */ WritePW (PR + IBL_DPC, dr_rom [IBL_DPC]); /* restore overwritten word */
WritePW (PC + IBL_END, dr_rom [IBL_END]); /* restore overwritten word */ WritePW (PR + IBL_END, dr_rom [IBL_END]); /* restore overwritten word */
PC = PC + BOOT_START; /* correct starting address */ PR = PR + BOOT_START; /* correct starting address */
return SCPE_OK; return SCPE_OK;
} }

View file

@ -25,6 +25,7 @@
IPLI, IPLO 12875A interprocessor link 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 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 14-Sep-15 JDB Exposed "ipl_edtdelay" via a REG_HIDDEN to allow user tuning
Corrected typos in comments and strings 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 */ IBL_SET_SC (devi) | devp)) /* the S register accordingly */
return SCPE_IERR; /* return an internal error if the copy failed */ return SCPE_IERR; /* return an internal error if the copy failed */
WritePW (PC + MAX_BASE, (~PC + 1) & DMASK); /* fix ups */ WritePW (PR + MAX_BASE, (~PR + 1) & DMASK); /* fix ups */
WritePW (PC + IPL_PNTR, ipl_rom [IPL_PNTR] | PC); WritePW (PR + IPL_PNTR, ipl_rom [IPL_PNTR] | PR);
WritePW (PC + PTR_PNTR, ipl_rom [PTR_PNTR] | PC); WritePW (PR + PTR_PNTR, ipl_rom [PTR_PNTR] | PR);
WritePW (PC + IPL_DEVA, devi); WritePW (PR + IPL_DEVA, devi);
WritePW (PC + PTR_DEVA, devp); WritePW (PR + PTR_DEVA, devp);
return SCPE_OK; return SCPE_OK;
} }

View file

@ -25,6 +25,7 @@
MPX 12792C 8-channel multiplexer card 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 28-Jul-16 JDB Fixed buffer ready check at read completion
Fixed terminate on character counts > 254 Fixed terminate on character counts > 254
13-May-16 JDB Modified for revised SCP API function parameter types 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 full), and if observed, the read buffer is terminated, and a read
buffer available UI condition is signalled. buffer available UI condition is signalled.
Implementation notes: Implementation notes:
1. The firmware echoes an entered BS before checking the buffer count to see 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 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 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. 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) t_stat mpx_line_svc (UNIT *uptr)
@ -1690,20 +1698,25 @@ 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 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_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 */ const t_bool fast_binary_read = (mpx_cmd == CMD_BINARY_READ); /* fast binary read in progress */
uint8 ch; uint8 ch;
int32 chx; int32 chx;
uint32 buffer_count, write_count;
t_stat status = SCPE_OK; t_stat status = SCPE_OK;
t_bool recv_loop = !fast_binary_read; /* bypass if fast binary read */ 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 */ t_bool xmit_loop = !(fast_binary_read || /* bypass if fast read or output suspended */
(mpx_flags [port] & (FL_WAITACK | FL_XOFF))); (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 */ /* Transmission service */
while (xmit_loop && (buf_len (iowrite, port, get) > 0)) { /* character available to output? */ write_count = buf_len (iowrite, port, get); /* get the output buffer length */
if ((mpx_flags [port] & FL_WREMPT) == 0) { /* has buffer started emptying? */
chx = buf_get (iowrite, port) << 8; /* get header value and position */ 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? */ if (fast_timing || (chx & WR_NO_ENQACK) || /* do we want handshake? */
!(mpx_config [port] & SK_ENQACK)) /* and configured for handshake? */ !(mpx_config [port] & SK_ENQACK)) /* and configured for handshake? */
@ -1711,7 +1724,7 @@ while (xmit_loop && (buf_len (iowrite, port, get) > 0)) { /* character availab
else 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? */ if (mpx_flags [port] & FL_DO_ENQACK) /* do handshake for this buffer? */
@ -1730,20 +1743,23 @@ while (xmit_loop && (buf_len (iowrite, port, get) > 0)) { /* character availab
else { /* not ready for ENQ */ else { /* not ready for ENQ */
ch = buf_get (iowrite, port) & data_mask; /* get char and mask to bit width */ 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 */ status = tmxr_putc_ln (&mpx_ldsc [port], ch); /* transmit the character */
xmit_loop = (status == SCPE_OK) && fast_timing; /* continue transmission? */
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? */ if (status != SCPE_OK) /* if the transmission failed */
DEBUG_PRI (mpx_dev, DEB_XFER)) 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", fprintf (sim_deb, ">>MPX xfer: Port %d character %s transmitted\n",
port, fmt_char (ch)); port, fmt_char (ch));
else if (write_count == 0) { /* buffer complete? */
xmit_loop = FALSE;
if (buf_len (iowrite, port, get) == 0) { /* buffer complete? */
buf_free (iowrite, port); /* free buffer */ 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? */ if (mpx_state == idle) /* controller idle? */
mpx_cntl_svc (&mpx_cntl); /* check for UI */ mpx_cntl_svc (&mpx_cntl); /* check for UI */
} }
@ -1752,6 +1768,11 @@ while (xmit_loop && (buf_len (iowrite, port, get) > 0)) { /* character availab
/* Reception service */ /* Reception service */
buffer_count = buf_avail (ioread, port); /* get the number of available read buffers */
if (mpx_flags [port] & FL_RDFILL) /* if filling the current buffer */
buffer_count = buffer_count + 1; /* then include it in the count */
while (recv_loop) { /* OK to process? */ while (recv_loop) { /* OK to process? */
chx = tmxr_getc_ln (&mpx_ldsc [port]); /* get a new character */ chx = tmxr_getc_ln (&mpx_ldsc [port]); /* get a new character */
@ -1805,7 +1826,7 @@ while (recv_loop) { /* OK to process? */
recv_loop = FALSE; /* absorb character */ 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_RDFILL)) { /* and not filling last buffer? */
mpx_flags [port] |= FL_RDOVFLOW; /* set buffer overflow flag */ mpx_flags [port] |= FL_RDOVFLOW; /* set buffer overflow flag */
recv_loop = fast_timing; /* continue loop if fast mode */ 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 */ mpx_param = mpx_param | RS_PARTIAL; /* and partial buffer flag */
} }
if (recv_loop) /* no termination condition? */ if (recv_loop) /* if there is no termination condition */
recv_loop = fast_timing; /* set to loop if fast mode */ 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)) { if (DEBUG_PRI (mpx_dev, DEB_XFER)) {
fprintf (sim_deb, ">>MPX xfer: Port %d read terminated on ", port); 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 */ else { /* normal service */
tmxr_poll_tx (&mpx_desc); /* output any accumulated characters */ tmxr_poll_tx (&mpx_desc); /* output any accumulated characters */
if ((buf_avail (iowrite, port) < 2) && /* more to transmit? */ if (write_count > 0 /* if there are more characters to transmit */
!(mpx_flags [port] & (FL_WAITACK | FL_XOFF)) || /* and transmission not suspended */ && !(mpx_flags [port] & (FL_WAITACK | FL_XOFF)) /* and transmission is not suspended */
tmxr_rqln (&mpx_ldsc [port])) /* or more to receive? */ || tmxr_rqln (&mpx_ldsc [port])) { /* or there are more characters to receive */
sim_activate (uptr, uptr->wait); /* reschedule service */ 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 else
if (DEBUG_PRI (mpx_dev, DEB_CMDS)) if (DEBUG_PRI (mpx_dev, DEB_CMDS))
fprintf (sim_deb, ">>MPX cmds: Port %d service stopped\n", port); fprintf (sim_deb, ">>MPX cmds: Port %d service stopped\n", port);