Fixed the fallback logic for IOPAGE ranges where only byte handlers exist (ie, the readROMByte() case)

This commit is contained in:
Jeff 2016-11-06 09:48:12 -08:00 committed by Jeff Parsons
commit 8188554875
6 changed files with 489 additions and 468 deletions

View file

@ -219,7 +219,7 @@ BusPDP11.IOHANDLER = {
* Unlike regular Memory blocks, IOPAGE accesses permit word accesses on ODD addresses; that works
* just fine by registering WORD handlers for the appropriate ODD addresses. For BYTE accesses, it
* depends. For CPU register addresses, addIOHandlers() installs special byte handlers that perform
* either a simple word read or write. Other addresses must be handled on case-by-case basis.
* either a simple word read or write. Other addresses must be handled on a case-by-case basis.
*
* TODO: Another small potential improvement would be for addIOHandlers() to install fallbacks for ALL
* missing handlers, in both the ODD and EVEN cases, so there's never a need to check each function index
@ -265,6 +265,13 @@ BusPDP11.IOController = {
if (afn) {
if (afn[BusPDP11.IOHANDLER.READ_WORD]) {
b = afn[BusPDP11.IOHANDLER.READ_WORD](addrMasked & ~0x1) >> 8;
} else if (afn[BusPDP11.IOHANDLER.READ_BYTE]) {
/*
* WARNING: This is an unusual fall-back, because we're trying to read an ODD byte
* access using a BYTE handler registered for EVEN bytes. But if that's all we've got,
* then presumably the handler is prepared for it (certainly, readROMByte() is).
*/
b = afn[BusPDP11.IOHANDLER.READ_BYTE](addrMasked)
}
}
}
@ -346,6 +353,13 @@ BusPDP11.IOController = {
w = afn[BusPDP11.IOHANDLER.READ_WORD]? afn[BusPDP11.IOHANDLER.READ_WORD](0) : 0;
afn[BusPDP11.IOHANDLER.WRITE_WORD]((w & 0xff) | (b << 8), addrMasked);
fWrite = true;
} else if (afn[BusPDP11.IOHANDLER.WRITE_BYTE]) {
/*
* WARNING: This is an unusual fall-back, because we're trying to write an ODD byte
* access using a BYTE handler registered for EVEN bytes. But if that's all we've got,
* then presumably the handler is prepared for it (certainly, writeROMByte() is).
*/
afn[BusPDP11.IOHANDLER.WRITE_BYTE](b, addrMasked);
}
}
}
@ -1239,7 +1253,7 @@ BusPDP11.prototype.restoreMemory = function(a)
* getMemorySize(type)
*
* NOTE: The original pdp11.js defined MAX_MEMORY as IOBASE_UNIBUS - 16384, where IOBASE_UNIBUS
* is 4Mb less 256Kb, and then subtracted another 16Kb so that BSD 2.9 could boot.
* is 4Mb less 256Kb, and then it subtracted another 16Kb so that BSD 2.9 could boot.
*
* @this {BusPDP11}
* @param {number} type is one of the MemoryPDP11.TYPE constants (only RAM is currently supported)
@ -1263,6 +1277,11 @@ BusPDP11.prototype.getMemorySize = function(type)
* relative to the starting IOPAGE address, but they can also be absolute; we simply mask all addresses with
* IOPAGE_MASK.
*
* CAVEATS: If a conflict is reported, a partial set of handlers may still have been added. There is no mechanism
* for removing handlers, since this is considered an initialization function. And finally, when a range of addresses
* is used, each successive address is advanced by 2, so if you really want to add a handler for a "+1" (usually odd)
* address, then you must add it individually.
*
* @this {BusPDP11}
* @param {number} start address
* @param {number} end address
@ -1319,8 +1338,8 @@ BusPDP11.prototype.addIOTable = function(component, table, msgCategory, sName)
var nRegs = afn[5] || 1;
/*
* As discussed in the IOController comments above, when handlers are being registered for the following
* addresses, we must install different fallback handlers for all BYTE accesses.
* As discussed in the IOController comments above, when handlers are being registered for these
* BYTE-granular UNIBUS addresses, we must install custom fallback handlers for all BYTE accesses.
*/
if (addr >= PDP11.UNIBUS.R0SET0 && addr <= PDP11.UNIBUS.R6USER) {
if (!fnReadByte && fnReadWord) {

View file

@ -507,8 +507,10 @@ var PDP11 = {
R6USER: 0o177717,
/*
* This next group of registers is largely ignored; all accesses are routed to regsControl[]
* This next group of registers is largely ignored; all accesses are routed to regsControl[],
* and therefore are managed as a block of 8 "CTRL" registers.
*/
CTRL: 0o177740,
LAERR: 0o177740, // Low Address Error (11/70 only)
HAERR: 0o177742, // High Address Error (11/70 only)
MEMERR: 0o177744, // Memory System Error (11/70 only)

View file

@ -835,7 +835,7 @@ DevicePDP11.prototype.writeR6USER = function(data, addr)
*/
DevicePDP11.prototype.readCTRL = function(addr)
{
var reg = (addr - PDP11.UNIBUS.LAERR) >> 1;
var reg = (addr - PDP11.UNIBUS.CTRL) >> 1;
return this.cpu.regsControl[reg];
};
@ -848,7 +848,7 @@ DevicePDP11.prototype.readCTRL = function(addr)
*/
DevicePDP11.prototype.writeCTRL = function(data, addr)
{
var reg = (addr - PDP11.UNIBUS.LAERR) >> 1;
var reg = (addr - PDP11.UNIBUS.CTRL) >> 1;
this.cpu.regsControl[reg] = data;
};
@ -1090,7 +1090,7 @@ DevicePDP11.UNIBUS_IOTABLE = {
[PDP11.UNIBUS.R5SET1]: /* 177715 */ [null, null, DevicePDP11.prototype.readRSET1, DevicePDP11.prototype.writeRSET1, "R5SET1", 1, PDP11.MODEL_1145],
[PDP11.UNIBUS.R6SUPER]: /* 177716 */ [null, null, DevicePDP11.prototype.readR6SUPER, DevicePDP11.prototype.writeR6SUPER, "R6SUPER", 1, PDP11.MODEL_1145],
[PDP11.UNIBUS.R6USER]: /* 177717 */ [null, null, DevicePDP11.prototype.readR6USER, DevicePDP11.prototype.writeR6USER, "R6USER", 1, PDP11.MODEL_1145],
[PDP11.UNIBUS.LAERR]: /* 177740 */ [null, null, DevicePDP11.prototype.readCTRL, DevicePDP11.prototype.writeCTRL, "CTRL", 1, PDP11.MODEL_1170],
[PDP11.UNIBUS.CTRL]: /* 177740 */ [null, null, DevicePDP11.prototype.readCTRL, DevicePDP11.prototype.writeCTRL, "CTRL", 8, PDP11.MODEL_1170],
[PDP11.UNIBUS.LSIZE]: /* 177760 */ [null, null, DevicePDP11.prototype.readSIZE, DevicePDP11.prototype.writeSIZE, "LSIZE", 1, PDP11.MODEL_1170],
[PDP11.UNIBUS.HSIZE]: /* 177762 */ [null, null, DevicePDP11.prototype.readSIZE, DevicePDP11.prototype.writeSIZE, "HSIZE", 1, PDP11.MODEL_1170],
[PDP11.UNIBUS.SYSID]: /* 177764 */ [null, null, DevicePDP11.prototype.readSYSID, DevicePDP11.prototype.writeSYSID, "SYSID", 1, PDP11.MODEL_1170],
@ -1101,14 +1101,6 @@ DevicePDP11.UNIBUS_IOTABLE = {
[PDP11.UNIBUS.PSW]: /* 177776 */ [null, null, DevicePDP11.prototype.readPSW, DevicePDP11.prototype.writePSW, "PSW"]
};
DevicePDP11.UNIBUS_IOTABLE[PDP11.UNIBUS.HAERR] = DevicePDP11.UNIBUS_IOTABLE[PDP11.UNIBUS.LAERR];
DevicePDP11.UNIBUS_IOTABLE[PDP11.UNIBUS.MEMERR] = DevicePDP11.UNIBUS_IOTABLE[PDP11.UNIBUS.LAERR];
DevicePDP11.UNIBUS_IOTABLE[PDP11.UNIBUS.CACHEC] = DevicePDP11.UNIBUS_IOTABLE[PDP11.UNIBUS.LAERR];
DevicePDP11.UNIBUS_IOTABLE[PDP11.UNIBUS.MAINT] = DevicePDP11.UNIBUS_IOTABLE[PDP11.UNIBUS.LAERR];
DevicePDP11.UNIBUS_IOTABLE[PDP11.UNIBUS.HITMISS]= DevicePDP11.UNIBUS_IOTABLE[PDP11.UNIBUS.LAERR];
DevicePDP11.UNIBUS_IOTABLE[PDP11.UNIBUS.UNDEF1] = DevicePDP11.UNIBUS_IOTABLE[PDP11.UNIBUS.LAERR];
DevicePDP11.UNIBUS_IOTABLE[PDP11.UNIBUS.UNDEF2] = DevicePDP11.UNIBUS_IOTABLE[PDP11.UNIBUS.LAERR];
/**
* DevicePDP11.init()
*

View file

@ -288,7 +288,7 @@ ROMPDP11.prototype.addROM = function(addr)
* This code has been added as a work-around to effectively allow us to install small ROMs into portions
* of the IOPAGE address space, by installing I/O handlers for the entire range that return the corresponding
* bytes of the current ROM image on reads, and ignore any writes (which I'm only assuming is how a typical
* ROM "device" deals with writes; if we remove the write handler, then writes will cause a fault).
* ROM "device" deals with writes; if we remove the write handler, then writes will fault).
*/
var IOTable = {
[addr]: [ROMPDP11.prototype.readROMByte, ROMPDP11.prototype.writeROMByte, null, null, null, this.sizeROM >> 1]
@ -348,6 +348,12 @@ ROMPDP11.prototype.readROMByte = function(addr)
/**
* writeROMByte(data, addr)
*
* This handler exists simply to ignore any writes, so that they don't cause faults.
*
* TODO: Another possible use for this would be to allow the Debugger to alter ROM contents,
* if the Debugger were to provide an interface indicating whether or not it was responsible
* for this write.
*
* @this {ROMPDP11}
* @param {number} data
* @param {number} addr