MicroVAX II, rtVAX1000: Fix NVR behavior to precisely reflect original hardware

Observations made about NVR behavior on real hardware:
    1) Aligned writes only affect a single RAM location
       without regard to the size of write, so no double
       pumping on writes.
    2) Unaligned (offset 3) writes do nothing without regard to size of the write
    3) Unaligned (offset 1) write 0 to the next higher NVR RAM location.
    4) Longword aligned and Unaligned (offset 3) reads return the same NVR RAM
       value in the the upper and lower words of the result.
    5) Unaligned (offset 1) reads reference the next higher NVR RAM cell for
       word and longword reads.

- Fix write behavior to match hardware.
- Fix read behavior to double pump word values for all unaligned word and longword
  reads.
This commit is contained in:
Mark Pizzolato 2016-04-26 12:32:13 -07:00
parent b502558df7
commit 2498fafd46

View file

@ -27,7 +27,7 @@
This module contains the MicroVAX II system-specific registers and devices. This module contains the MicroVAX II system-specific registers and devices.
rom bootstrap ROM (no registers) rom bootstrap ROM (no registers)
nvr non-volatile ROM (no registers) nvr non-volatile RAM (no registers)
sysd system devices sysd system devices
08-Nov-2012 MB First version 08-Nov-2012 MB First version
@ -431,16 +431,16 @@ return "read-only memory";
int32 nvr_rd (int32 pa) int32 nvr_rd (int32 pa)
{ {
int32 rg = (pa - NVRBASE) >> 1; int32 rg = (pa + 1 - NVRBASE) >> 1;
int32 result; int32 result;
if (rg < 14) /* watch chip */ if (rg < 14) /* watch chip */
result = wtc_rd (pa); result = wtc_rd (pa);
else else {
if (rg & 1) result = (nvr[rg] & WMASK) | (((uint32)nvr[rg]) << 16);
result = ((int32)nvr[rg]) << 16; if (pa & 1)
else result = result << 8;
result = nvr[rg] | (((int32)nvr[rg+1]) << 16); }
sim_debug (DBG_REG, &nvr_dev, "nvr_rd(pa=0x%X) nvr[0x%X] returns: 0x%X\n", pa, rg, result); sim_debug (DBG_REG, &nvr_dev, "nvr_rd(pa=0x%X) nvr[0x%X] returns: 0x%X\n", pa, rg, result);
@ -449,21 +449,21 @@ return result;
void nvr_wr (int32 pa, int32 val, int32 lnt) void nvr_wr (int32 pa, int32 val, int32 lnt)
{ {
int32 rg = (pa - NVRBASE) >> 1; int32 rg = (pa + 1 - NVRBASE) >> 1;
if (rg < 14) /* watch chip */ if (rg < 14) /* watch chip */
wtc_wr (pa, val, lnt); wtc_wr (pa, val, lnt);
else { else {
int32 orig_nvr = (int32)nvr[rg]; int32 orig_nvr = (int32)nvr[rg];
int32 v = val;
int32 r = rg;
int32 l = lnt;
while (l > 0) { switch (pa & 03) {
nvr[r] = (uint8)v; case 0:
++r; case 2:
l -= 2; nvr[rg] = (uint8)val;
v = (v >> 16); break;
case 1:
nvr[rg] = 0;
break;
} }
if (lnt > 1) if (lnt > 1)
@ -784,7 +784,9 @@ MACH_CHECK (MCHK_READ);
int32 ReadRegU (uint32 pa, int32 lnt) int32 ReadRegU (uint32 pa, int32 lnt)
{ {
if (lnt == L_BYTE)
return ReadReg (pa & ~03, L_LONG); return ReadReg (pa & ~03, L_LONG);
return (ReadReg (pa & ~03, L_WORD) & WMASK) | (ReadReg ((pa & ~03) + 2, L_WORD) & (WMASK << 16));
} }
/* WriteReg - write register space /* WriteReg - write register space