Fixed the fallback logic for IOPAGE ranges where only byte handlers exist (ie, the readROMByte() case)
This commit is contained in:
parent
9e00cd4dad
commit
8188554875
6 changed files with 489 additions and 468 deletions
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
*
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Reference in a new issue