Simplify the Bus and Memory interfaces slightly, by enabling WORDBUS, which treats all word accesses as aligned; the CPU is has sole responsibility for detecting unaligned word addresses and trapping appropriatelu
This commit is contained in:
parent
f7659f9f34
commit
1a1614a648
12 changed files with 444 additions and 398 deletions
|
|
@ -253,7 +253,7 @@ C1PComputer.power = function(computer)
|
|||
/*
|
||||
* C1PComputer.init()
|
||||
*
|
||||
* This function operates on every HTML element of class "computer", extracting the
|
||||
* This function operates on every HTML element of class "c1pjs-computer", extracting the
|
||||
* JSON-encoded parameters for the C1PComputer constructor from the element's "data-value"
|
||||
* attribute, invoking the constructor to create a C1PComputer component, and then binding
|
||||
* any associated HTML controls to the new component.
|
||||
|
|
@ -263,7 +263,7 @@ C1PComputer.init = function()
|
|||
/*
|
||||
* In non-COMPILED builds, embedMachine() may have set XMLVERSION.
|
||||
*/
|
||||
if (!COMPILED && C1PJS.XMLVERSION) C1PJS.APPVERSION = C1PJS.XMLVERSION;
|
||||
if (!COMPILED && XMLVERSION) C1PJS.APPVERSION = XMLVERSION;
|
||||
|
||||
var aeComputers = Component.getElementsByClass(document, C1PJS.APPCLASS, "computer");
|
||||
|
||||
|
|
|
|||
|
|
@ -1488,7 +1488,7 @@ Computer8080.prototype.updateVideo = function(fForced)
|
|||
/**
|
||||
* Computer8080.init()
|
||||
*
|
||||
* For every machine represented by an HTML element of class "pcjs-machine", this function
|
||||
* For every machine represented by an HTML element of class "pc8080-machine", this function
|
||||
* locates the HTML element of class "computer", extracting the JSON-encoded parameters for the
|
||||
* Computer constructor from the element's "data-value" attribute, invoking the constructor to
|
||||
* create a Computer component, and then binding any associated HTML controls to the new component.
|
||||
|
|
@ -1498,7 +1498,7 @@ Computer8080.init = function()
|
|||
/*
|
||||
* In non-COMPILED builds, embedMachine() may have set XMLVERSION.
|
||||
*/
|
||||
if (!COMPILED && PC8080.XMLVERSION) PC8080.APPVERSION = PC8080.XMLVERSION;
|
||||
if (!COMPILED && XMLVERSION) PC8080.APPVERSION = XMLVERSION;
|
||||
|
||||
var aeMachines = Component.getElementsByClass(document, PC8080.APPCLASS + "-machine");
|
||||
|
||||
|
|
|
|||
|
|
@ -1518,7 +1518,7 @@ Computer.prototype.updateVideo = function(fForce)
|
|||
/**
|
||||
* Computer.init()
|
||||
*
|
||||
* For every machine represented by an HTML element of class "pcjs-machine", this function
|
||||
* For every machine represented by an HTML element of class "pcx86-machine", this function
|
||||
* locates the HTML element of class "computer", extracting the JSON-encoded parameters for the
|
||||
* Computer constructor from the element's "data-value" attribute, invoking the constructor to
|
||||
* create a Computer component, and then binding any associated HTML controls to the new component.
|
||||
|
|
@ -1528,7 +1528,7 @@ Computer.init = function()
|
|||
/*
|
||||
* In non-COMPILED builds, embedMachine() may have set XMLVERSION.
|
||||
*/
|
||||
if (!COMPILED && PCX86.XMLVERSION) PCX86.APPVERSION = PCX86.XMLVERSION;
|
||||
if (!COMPILED && XMLVERSION) PCX86.APPVERSION = XMLVERSION;
|
||||
|
||||
var aeMachines = Component.getElementsByClass(document, PCX86.APPCLASS + "-machine");
|
||||
|
||||
|
|
|
|||
|
|
@ -133,7 +133,7 @@ function BusPDP11(parmsBus, cpu, dbg)
|
|||
this.fIOBreakAll = false;
|
||||
|
||||
this.fnReset = null;
|
||||
this.fnAccess = this.access;
|
||||
this.fnIOAccess = this.unknownIO;
|
||||
|
||||
/*
|
||||
* Allocate empty Memory blocks to span the entire physical address space.
|
||||
|
|
@ -214,7 +214,7 @@ BusPDP11.IOController = {
|
|||
}
|
||||
return b;
|
||||
}
|
||||
b = bus.fnAccess(addr | BusPDP11.IOPAGE_22BIT, -1, 1);
|
||||
b = bus.fnIOAccess(addr | BusPDP11.IOPAGE_22BIT, -1, 1);
|
||||
if (DEBUGGER && this.dbg && this.dbg.messageEnabled(MessagesPDP11.BUS)) {
|
||||
this.dbg.printMessage("warning: unconverted read access to byte @" + this.dbg.toStrBase(addr) + ": " + this.dbg.toStrBase(b));
|
||||
}
|
||||
|
|
@ -279,7 +279,7 @@ BusPDP11.IOController = {
|
|||
}
|
||||
return;
|
||||
}
|
||||
bus.fnAccess(addr | BusPDP11.IOPAGE_22BIT, b, 1);
|
||||
bus.fnIOAccess(addr | BusPDP11.IOPAGE_22BIT, b, 1);
|
||||
if (DEBUGGER && this.dbg && this.dbg.messageEnabled(MessagesPDP11.BUS)) {
|
||||
this.dbg.printMessage("warning: unconverted write access to byte @" + this.dbg.toStrBase(addr) + ": " + this.dbg.toStrBase(b));
|
||||
}
|
||||
|
|
@ -312,7 +312,7 @@ BusPDP11.IOController = {
|
|||
}
|
||||
return w;
|
||||
}
|
||||
w = bus.fnAccess(addr | BusPDP11.IOPAGE_22BIT, -1, 0);
|
||||
w = bus.fnIOAccess(addr | BusPDP11.IOPAGE_22BIT, -1, 0);
|
||||
if (DEBUGGER && this.dbg && this.dbg.messageEnabled(MessagesPDP11.BUS)) {
|
||||
this.dbg.printMessage("warning: unconverted read access to word @" + this.dbg.toStrBase(addr) + ": " + this.dbg.toStrBase(w));
|
||||
}
|
||||
|
|
@ -349,7 +349,7 @@ BusPDP11.IOController = {
|
|||
}
|
||||
return;
|
||||
}
|
||||
bus.fnAccess(addr | BusPDP11.IOPAGE_22BIT, w, 0);
|
||||
bus.fnIOAccess(addr | BusPDP11.IOPAGE_22BIT, w, 0);
|
||||
if (DEBUGGER && this.dbg && this.dbg.messageEnabled(MessagesPDP11.BUS)) {
|
||||
this.dbg.printMessage("warning: unconverted write access to word @" + this.dbg.toStrBase(addr) + ": " + this.dbg.toStrBase(w));
|
||||
}
|
||||
|
|
@ -426,7 +426,7 @@ BusPDP11.prototype.reset = function()
|
|||
};
|
||||
|
||||
/**
|
||||
* access(addr, data, byteFlag)
|
||||
* unknownIO(addr, data, byteFlag)
|
||||
*
|
||||
* This is our default I/O handler, called whenever there's an IOPAGE access without a corresponding entry
|
||||
* in aIOHandlers; in the interim, our Device component will override this default handler with its own function
|
||||
|
|
@ -438,10 +438,10 @@ BusPDP11.prototype.reset = function()
|
|||
* @param {number} data (-1 if read, otherwise write)
|
||||
* @param {number} byteFlag (true if byte I/O, otherwise word)
|
||||
*/
|
||||
BusPDP11.prototype.access = function(addr, data, byteFlag)
|
||||
BusPDP11.prototype.unknownIO = function(addr, data, byteFlag)
|
||||
{
|
||||
if (DEBUGGER && this.dbg && this.dbg.messageEnabled(MessagesPDP11.BUS)) {
|
||||
this.dbg.printMessage("warning: unrecognized access(" + this.dbg.toStrBase(addr) + "," + this.dbg.toStrBase(data) + "," + byteFlag + ")");
|
||||
this.dbg.printMessage("warning: unrecognized I/O access(" + this.dbg.toStrBase(addr) + "," + this.dbg.toStrBase(data) + "," + byteFlag + ")");
|
||||
}
|
||||
return 0;
|
||||
};
|
||||
|
|
@ -808,10 +808,10 @@ BusPDP11.prototype.getWord = function(addr)
|
|||
{
|
||||
var off = addr & this.nBlockLimit;
|
||||
var iBlock = (addr & this.nBusMask) >>> this.nBlockShift;
|
||||
if (off != this.nBlockLimit) {
|
||||
return this.aMemBlocks[iBlock].readWord(off, addr);
|
||||
if (!PDP11.WORDBUS && off == this.nBlockLimit) {
|
||||
return this.aMemBlocks[iBlock++].readByte(off, addr) | (this.aMemBlocks[iBlock & this.nBlockMask].readByte(0, addr + 1) << 8);
|
||||
}
|
||||
return this.aMemBlocks[iBlock++].readByte(off, addr) | (this.aMemBlocks[iBlock & this.nBlockMask].readByte(0, addr + 1) << 8);
|
||||
return this.aMemBlocks[iBlock].readWord(off, addr);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -827,10 +827,10 @@ BusPDP11.prototype.getWordDirect = function(addr)
|
|||
{
|
||||
var off = addr & this.nBlockLimit;
|
||||
var iBlock = (addr & this.nBusMask) >>> this.nBlockShift;
|
||||
if (off != this.nBlockLimit) {
|
||||
return this.aMemBlocks[iBlock].readWordDirect(off, addr);
|
||||
if (!PDP11.WORDBUS && off == this.nBlockLimit) {
|
||||
return this.aMemBlocks[iBlock++].readByteDirect(off, addr) | (this.aMemBlocks[iBlock & this.nBlockMask].readByteDirect(0, addr + 1) << 8);
|
||||
}
|
||||
return this.aMemBlocks[iBlock++].readByteDirect(off, addr) | (this.aMemBlocks[iBlock & this.nBlockMask].readByteDirect(0, addr + 1) << 8);
|
||||
return this.aMemBlocks[iBlock].readWordDirect(off, addr);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -871,12 +871,12 @@ BusPDP11.prototype.setWord = function(addr, w)
|
|||
{
|
||||
var off = addr & this.nBlockLimit;
|
||||
var iBlock = (addr & this.nBusMask) >>> this.nBlockShift;
|
||||
if (off != this.nBlockLimit) {
|
||||
this.aMemBlocks[iBlock].writeWord(off, w & 0xffff, addr);
|
||||
if (!PDP11.WORDBUS && off == this.nBlockLimit) {
|
||||
this.aMemBlocks[iBlock++].writeByte(off, w & 0xff, addr);
|
||||
this.aMemBlocks[iBlock & this.nBlockMask].writeByte(0, (w >> 8) & 0xff, addr + 1);
|
||||
return;
|
||||
}
|
||||
this.aMemBlocks[iBlock++].writeByte(off, w & 0xff, addr);
|
||||
this.aMemBlocks[iBlock & this.nBlockMask].writeByte(0, (w >> 8) & 0xff, addr + 1);
|
||||
this.aMemBlocks[iBlock].writeWord(off, w & 0xffff, addr);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -893,12 +893,12 @@ BusPDP11.prototype.setWordDirect = function(addr, w)
|
|||
{
|
||||
var off = addr & this.nBlockLimit;
|
||||
var iBlock = (addr & this.nBusMask) >>> this.nBlockShift;
|
||||
if (off != this.nBlockLimit) {
|
||||
this.aMemBlocks[iBlock].writeWordDirect(off, w & 0xffff, addr);
|
||||
if (!PDP11.WORDBUS && off == this.nBlockLimit) {
|
||||
this.aMemBlocks[iBlock++].writeByteDirect(off, w & 0xff, addr);
|
||||
this.aMemBlocks[iBlock & this.nBlockMask].writeByteDirect(0, (w >> 8) & 0xff, addr + 1);
|
||||
return;
|
||||
}
|
||||
this.aMemBlocks[iBlock++].writeByteDirect(off, w & 0xff, addr);
|
||||
this.aMemBlocks[iBlock & this.nBlockMask].writeByteDirect(0, (w >> 8) & 0xff, addr + 1);
|
||||
this.aMemBlocks[iBlock].writeWordDirect(off, w & 0xffff, addr);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -1072,18 +1072,18 @@ BusPDP11.prototype.addIOTable = function(component, table)
|
|||
};
|
||||
|
||||
/**
|
||||
* addIODefaultHandlers(fnReset, fnAccess)
|
||||
* addIODefaultHandlers(fnReset, fnIOAccess)
|
||||
*
|
||||
* Add default I/O notification handlers.
|
||||
*
|
||||
* @this {BusPDP11}
|
||||
* @param {function()} fnReset
|
||||
* @param {function(number,number,number)} fnAccess
|
||||
* @param {function(number,number,number)} fnIOAccess
|
||||
*/
|
||||
BusPDP11.prototype.addIODefaultHandlers = function(fnReset, fnAccess)
|
||||
BusPDP11.prototype.addIODefaultHandlers = function(fnReset, fnIOAccess)
|
||||
{
|
||||
this.fnReset = fnReset;
|
||||
this.fnAccess = fnAccess;
|
||||
this.fnIOAccess = fnIOAccess;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -1448,7 +1448,7 @@ ComputerPDP11.prototype.updateStatus = function(fForce)
|
|||
/**
|
||||
* ComputerPDP11.init()
|
||||
*
|
||||
* For every machine represented by an HTML element of class "pcjs-machine", this function
|
||||
* For every machine represented by an HTML element of class "pdp11-machine", this function
|
||||
* locates the HTML element of class "computer", extracting the JSON-encoded parameters for the
|
||||
* Computer constructor from the element's "data-value" attribute, invoking the constructor to
|
||||
* create a Computer component, and then binding any associated HTML controls to the new component.
|
||||
|
|
|
|||
|
|
@ -1094,12 +1094,18 @@ CPUStatePDP11.prototype.mapVirtualToPhysical = function(virtualAddress, accessFl
|
|||
this.mmuLastVirtual = physicalAddress;
|
||||
if (physicalAddress >= BusPDP11.IOPAGE_VIRT) {
|
||||
physicalAddress |= BusPDP11.IOPAGE_22BIT;
|
||||
} else { // no max_memory check in 16 bit mode
|
||||
}
|
||||
/*
|
||||
* I'm moving this alignment test to the CPU->Bus interfaces that read/write physical words;
|
||||
* hopefully there are no order dependencies on this test.
|
||||
*
|
||||
else { // no max_memory check in 16 bit mode
|
||||
if ((physicalAddress & 1) && !(accessFlags & PDP11.ACCESS.BYTE)) {
|
||||
this.regErr |= PDP11.CPUERR.ODDADDR;
|
||||
this.trap(PDP11.TRAP.BUS_ERROR, PDP11.REASON.ODDMEMADDR);
|
||||
}
|
||||
}
|
||||
*/
|
||||
} else {
|
||||
this.mmuLastVirtual = virtualAddress;
|
||||
page = (virtualAddress >> 13) & this.mmuMask[this.mmuMode];
|
||||
|
|
@ -1118,10 +1124,15 @@ CPUStatePDP11.prototype.mapVirtualToPhysical = function(virtualAddress, accessFl
|
|||
this.regErr |= PDP11.CPUERR.NOMEMORY;
|
||||
this.trap(PDP11.TRAP.BUS_ERROR, PDP11.REASON.NOMEMORY); // KB11-EM does this after ABORT handling - KB11-CM before
|
||||
}
|
||||
/*
|
||||
* I'm moving this alignment test to the CPU->Bus interfaces that read/write physical words;
|
||||
* hopefully there are no order dependencies on this test.
|
||||
*
|
||||
if ((physicalAddress & 1) && !(accessFlags & PDP11.ACCESS.BYTE)) {
|
||||
this.regErr |= PDP11.CPUERR.ODDADDR;
|
||||
this.trap(PDP11.TRAP.BUS_ERROR, PDP11.REASON.ODDMMUADDR);
|
||||
}
|
||||
*/
|
||||
}
|
||||
switch (pdr & 0x7) {
|
||||
case 1: // read-only with trap
|
||||
|
|
@ -1190,6 +1201,18 @@ CPUStatePDP11.prototype.mapVirtualToPhysical = function(virtualAddress, accessFl
|
|||
return physicalAddress;
|
||||
};
|
||||
|
||||
/**
|
||||
* readByteFromPhysical(physicalAddress) [formerly readByteByAddr]
|
||||
*
|
||||
* @this {CPUStatePDP11}
|
||||
* @param {number} physicalAddress
|
||||
* @return {number}
|
||||
*/
|
||||
CPUStatePDP11.prototype.readByteFromPhysical = function(physicalAddress)
|
||||
{
|
||||
return this.bus.getByte(physicalAddress);
|
||||
};
|
||||
|
||||
/**
|
||||
* readWordFromPhysical(physicalAddress) [formerly readWordByAddr]
|
||||
*
|
||||
|
|
@ -1199,6 +1222,10 @@ CPUStatePDP11.prototype.mapVirtualToPhysical = function(virtualAddress, accessFl
|
|||
*/
|
||||
CPUStatePDP11.prototype.readWordFromPhysical = function(physicalAddress)
|
||||
{
|
||||
if (physicalAddress & 0x1) {
|
||||
this.regErr |= PDP11.CPUERR.ODDADDR;
|
||||
this.trap(PDP11.TRAP.BUS_ERROR, PDP11.REASON.ODDMEMADDR);
|
||||
}
|
||||
return this.bus.getWord(physicalAddress);
|
||||
};
|
||||
|
||||
|
|
@ -1213,30 +1240,6 @@ CPUStatePDP11.prototype.readWordFromVirtual = function(virtualAddress)
|
|||
return this.readWordFromPhysical(this.mapVirtualToPhysical(virtualAddress, PDP11.ACCESS.READ_WORD));
|
||||
};
|
||||
|
||||
/**
|
||||
* writeWordToPhysical(physicalAddress, data) [formerly writeWordByAddr]
|
||||
*
|
||||
* @this {CPUStatePDP11}
|
||||
* @param {number} physicalAddress
|
||||
* @param {number} data
|
||||
*/
|
||||
CPUStatePDP11.prototype.writeWordToPhysical = function(physicalAddress, data)
|
||||
{
|
||||
this.bus.setWord(physicalAddress, data & 0xffff);
|
||||
};
|
||||
|
||||
/**
|
||||
* readByteFromPhysical(physicalAddress) [formerly readByteByAddr]
|
||||
*
|
||||
* @this {CPUStatePDP11}
|
||||
* @param {number} physicalAddress
|
||||
* @return {number}
|
||||
*/
|
||||
CPUStatePDP11.prototype.readByteFromPhysical = function(physicalAddress)
|
||||
{
|
||||
return this.bus.getByte(physicalAddress);
|
||||
};
|
||||
|
||||
/**
|
||||
* writeByteToPhysical(physicalAddress, data) [formerly writeByteByAddr]
|
||||
*
|
||||
|
|
@ -1250,6 +1253,22 @@ CPUStatePDP11.prototype.writeByteToPhysical = function(physicalAddress, data)
|
|||
this.bus.setByte(physicalAddress, data & 0xff);
|
||||
};
|
||||
|
||||
/**
|
||||
* writeWordToPhysical(physicalAddress, data) [formerly writeWordByAddr]
|
||||
*
|
||||
* @this {CPUStatePDP11}
|
||||
* @param {number} physicalAddress
|
||||
* @param {number} data
|
||||
*/
|
||||
CPUStatePDP11.prototype.writeWordToPhysical = function(physicalAddress, data)
|
||||
{
|
||||
if (physicalAddress & 0x1) {
|
||||
this.regErr |= PDP11.CPUERR.ODDADDR;
|
||||
this.trap(PDP11.TRAP.BUS_ERROR, PDP11.REASON.ODDMEMADDR);
|
||||
}
|
||||
this.bus.setWord(physicalAddress, data & 0xffff);
|
||||
};
|
||||
|
||||
/**
|
||||
* popWord()
|
||||
*
|
||||
|
|
|
|||
|
|
@ -590,7 +590,7 @@ if (DEBUGGER) {
|
|||
if (addr !== PDP11.ADDR_INVALID) {
|
||||
this.nDisableMessages++;
|
||||
/*
|
||||
* TODO: We also need a Bus interface to disable fnAccess() calls that could trigger a trap()
|
||||
* TODO: We also need a Bus interface to disable fnIOAccess() calls that could trigger a trap().
|
||||
*/
|
||||
b = this.bus.getByteDirect(addr);
|
||||
this.nDisableMessages--;
|
||||
|
|
@ -614,7 +614,11 @@ if (DEBUGGER) {
|
|||
if (addr !== PDP11.ADDR_INVALID) {
|
||||
this.nDisableMessages++;
|
||||
/*
|
||||
* TODO: We also need a Bus interface to disable fnAccess() calls that could trigger a trap()
|
||||
* TODO: We also need a Bus interface to disable fnIOAccess() calls that could trigger a trap().
|
||||
*
|
||||
* NOTE: We don't care if the word address is aligned, because 1) we assume the user knows what
|
||||
* they're doing, and 2) the Bus simply ignores the low address bit anyway. Alignment checks are
|
||||
* performed by the CPU, not the Bus.
|
||||
*/
|
||||
w = this.bus.getWordDirect(addr);
|
||||
this.nDisableMessages--;
|
||||
|
|
@ -637,7 +641,7 @@ if (DEBUGGER) {
|
|||
if (addr !== PDP11.ADDR_INVALID) {
|
||||
this.nDisableMessages++;
|
||||
/*
|
||||
* TODO: We also need a Bus interface to disable fnAccess() calls that could trigger a trap()
|
||||
* TODO: We also need a Bus interface to disable fnIOAccess() calls that could trigger a trap().
|
||||
*/
|
||||
this.bus.setByteDirect(addr, b);
|
||||
this.nDisableMessages--;
|
||||
|
|
@ -660,7 +664,11 @@ if (DEBUGGER) {
|
|||
if (addr !== PDP11.ADDR_INVALID) {
|
||||
this.nDisableMessages++;
|
||||
/*
|
||||
* TODO: We also need a Bus interface to disable fnAccess() calls that could trigger a trap()
|
||||
* TODO: We also need a Bus interface to disable fnIOAccess() calls that could trigger a trap().
|
||||
*
|
||||
* NOTE: We don't care if the word address is aligned, because 1) we assume the user knows what
|
||||
* they're doing, and 2) the Bus simply ignores the low address bit anyway. Alignment checks are
|
||||
* performed by the CPU, not the Bus.
|
||||
*/
|
||||
this.bus.setWordDirect(addr, w);
|
||||
this.nDisableMessages--;
|
||||
|
|
@ -2841,15 +2849,14 @@ if (DEBUGGER) {
|
|||
var sData = "", sChars = "";
|
||||
sAddr = this.toStrAddr(dbgAddr);
|
||||
/*
|
||||
* It's just coincidence that we want to dump 8 bytes per line when using base 8 and 16 bytes
|
||||
* per line when using base 16, because octal requires more digits.
|
||||
* Dump 8 bytes per line when using base 8, and dump 16 bytes when using base 16 (or when dumping dwords)
|
||||
*/
|
||||
var nBytes = (size == 4? 16 : this.nBase);
|
||||
for (i = nBytes; i > 0 && cb > 0; i--) {
|
||||
var b = this.getByte(dbgAddr, 1);
|
||||
data |= (b << (iByte++ << 3));
|
||||
if (iByte == size) {
|
||||
sData += (this.nBase == 8? str.toOct(data, size * 3) : str.toHex(data, size * 2));
|
||||
sData += this.toStrBase(data, size);
|
||||
sData += (size == 1? (i == 9? '-' : ' ') : " ");
|
||||
data = iByte = 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -79,6 +79,21 @@ var BYTEARRAYS = false;
|
|||
*/
|
||||
var TYPEDARRAYS = (typeof ArrayBuffer !== 'undefined');
|
||||
|
||||
/**
|
||||
* WORDBUS forces the Bus and Memory interfaces to assume even addresses when accessing words. Since PDPjs inherited
|
||||
* its Bus component from PCx86, it originally supported both aligned and unaligned word accesses by default, but since
|
||||
* the PDP-11 requires aligned (even) word addresses, we can turn off support for unaligned accesses and get some
|
||||
* performance gains.
|
||||
*
|
||||
* When WORDBUS is true, the Bus and Memory components simply ignore the low bit of word addresses, because it is the
|
||||
* CPU, not the Bus, that's responsible for validating addresses and generating the appropriate traps.
|
||||
*
|
||||
* Don't worry that the source code looks MORE complicated rather than LESS with the additional WORDBUS checks, because
|
||||
* the Closure Compiler eliminates those checks and throws away the (unreachable) code blocks that deal with unaligned
|
||||
* accesses.
|
||||
*/
|
||||
var WORDBUS = true;
|
||||
|
||||
/*
|
||||
* Combine all the shared globals and machine-specific globals into one machine-specific global object,
|
||||
* which all machine components should start using; eg: "if (PDP11.DEBUG) ..." instead of "if (DEBUG) ...".
|
||||
|
|
@ -95,6 +110,7 @@ var PDP11 = {
|
|||
MAXDEBUG: MAXDEBUG, // shared
|
||||
PRIVATE: PRIVATE, // shared
|
||||
TYPEDARRAYS:TYPEDARRAYS,
|
||||
WORDBUS: WORDBUS,
|
||||
SITEHOST: SITEHOST, // shared
|
||||
XMLVERSION: XMLVERSION, // shared
|
||||
|
||||
|
|
|
|||
|
|
@ -782,10 +782,15 @@ MemoryPDP11.prototype = {
|
|||
*/
|
||||
readWordLE: function readWordLE(off, addr) {
|
||||
/*
|
||||
* TODO: It remains to be seen if there's any advantage to checking the offset for an aligned read
|
||||
* vs. always reading the bytes separately.
|
||||
* TODO: For non-WORDBUS machines, it remains to be seen if there's any advantage to checking the offset
|
||||
* for an aligned read vs. always reading the bytes separately.
|
||||
*/
|
||||
var w = (off & 0x1)? (this.ab[off] | (this.ab[off+1] << 8)) : this.aw[off >> 1];
|
||||
var w;
|
||||
if (PDP11.WORDBUS || !(off & 0x1)) {
|
||||
w = this.aw[off >> 1];
|
||||
} else {
|
||||
w = this.ab[off] | (this.ab[off+1] << 8);
|
||||
}
|
||||
if (DEBUGGER && this.dbg && this.dbg.messageEnabled(MessagesPDP11.MEM)) {
|
||||
this.dbg.printMessage("Memory.readWord(" + this.dbg.toStrBase(addr) + "): " + this.dbg.toStrBase(w), true);
|
||||
}
|
||||
|
|
@ -840,14 +845,14 @@ MemoryPDP11.prototype = {
|
|||
*/
|
||||
writeWordLE: function writeWordLE(off, w, addr) {
|
||||
/*
|
||||
* TODO: It remains to be seen if there's any advantage to checking the offset for an aligned write
|
||||
* vs. always writing the bytes separately.
|
||||
* TODO: For non-WORDBUS machines, it remains to be seen if there's any advantage to checking the offset
|
||||
* for an aligned write vs. always writing the bytes separately.
|
||||
*/
|
||||
if (off & 0x1) {
|
||||
if (PDP11.WORDBUS || !(off & 0x1)) {
|
||||
this.aw[off >> 1] = w;
|
||||
} else {
|
||||
this.ab[off] = w;
|
||||
this.ab[off+1] = w >> 8;
|
||||
} else {
|
||||
this.aw[off >> 1] = w;
|
||||
}
|
||||
this.fDirty = true;
|
||||
if (DEBUGGER && this.dbg && this.dbg.messageEnabled(MessagesPDP11.MEM)) {
|
||||
|
|
|
|||
Loading…
Reference in a new issue