New improved I/O handler functions for the PDP-11

This commit is contained in:
Jeff 2016-09-21 12:44:25 -07:00 committed by Jeff Parsons
commit dfe367f53d
18 changed files with 847 additions and 1059 deletions

View file

@ -76,35 +76,16 @@ function Bus8080(parmsBus, cpu, dbg)
this.nBusWidth = parmsBus['busWidth'] || 16;
/*
* Compute all Bus8080 memory block parameters, based on the width of the bus.
*
* Regarding blockTotal, we want to avoid using block overflow expressions like:
*
* iBlock < this.nBlockTotal? iBlock : 0
*
* As long as we know that blockTotal is a power of two (eg, 256 or 0x100, in the case of
* nBusWidth == 20 and blockSize == 4096), we can define blockMask as (blockTotal - 1) and
* rewrite the previous expression as:
*
* iBlock & this.nBlockMask
*
* Bus Property Old hard-coded values (when nBusWidth was always 20)
* ------------ ----------------------------------------------------
* this.nBusLimit 0xfffff
* this.nBusMask [same as busLimit]
* this.nBlockSize 4096
* this.nBlockLen (this.nBlockSize >> 2)
* this.nBlockShift 12
* this.nBlockLimit 0xfff
* this.nBlockTotal ((this.nBusLimit + this.nBlockSize) / this.nBlockSize) | 0
* this.nBlockMask (this.nBlockTotal - 1) [ie, 0xff]
*
* Note that we choose a nBlockShift value (and thus a physical memory block size) based on "buswidth":
* Compute all Bus8080 memory block parameters, based on the width of the bus. The entire
* address space is divided into blocks, using a block size that is (hopefully) appropriate to
* the bus width. The following table summarizes our simplistic calculations.
*
* Bus Width Block Shift Block Size
* --------- ----------- ----------
* 16 bits (64Kb address space): 10 1Kb (64 maximum blocks)
* 18 bits (256Kb address space): 11 2Kb (128 maximum blocks)
* 20 bits (1Mb address space): 12 4Kb (256 maximum blocks)
* 22 bits (4Mb address space): 13 8Kb (512 maximum blocks)
* 24 bits (16Mb address space): 14 16Kb (1K maximum blocks)
* 32 bits (4Gb address space); 15 32Kb (128K maximum blocks)
*
@ -115,7 +96,9 @@ function Bus8080(parmsBus, cpu, dbg)
*/
this.addrTotal = Math.pow(2, this.nBusWidth);
this.nBusLimit = this.nBusMask = (this.addrTotal - 1) | 0;
this.nBlockShift = (this.nBusWidth <= 16)? 10 : ((this.nBusWidth <= 20)? 12 : (this.nBusWidth <= 24? 14 : 15));
this.nBlockShift = (this.nBusWidth >> 1) + 2;
if (this.nBlockShift < 10) this.nBlockShift = 10;
if (this.nBlockShift > 15) this.nBlockShift = 15;
this.nBlockSize = 1 << this.nBlockShift;
this.nBlockLen = this.nBlockSize >> 2;
this.nBlockLimit = this.nBlockSize - 1;
@ -173,38 +156,6 @@ Bus8080.ERROR = {
REM_MEM_BADRANGE: 5
};
/**
* @typedef {number}
*/
var BlockInfo;
/**
* This defines the BlockInfo bit fields used by scanMemory() when it creates the aBlocks array.
*
* @typedef {{
* num: BitField,
* count: BitField,
* btmod: BitField,
* type: BitField
* }}
*/
Bus8080.BlockInfo = usr.defineBitFields({num:20, count:8, btmod:1, type:3});
/**
* BusInfo8080 object definition (returned by scanMemory())
*
* cbTotal: total bytes allocated
* cBlocks: total Memory blocks allocated
* aBlocks: array of allocated Memory block numbers
*
* @typedef {{
* cbTotal: number,
* cBlocks: number,
* aBlocks: Array.<BlockInfo>
* }}
*/
var BusInfo8080;
/**
* initMemory()
*
@ -361,6 +312,42 @@ Bus8080.prototype.cleanMemory = function(addr, size)
return fClean;
};
/*
* Data types used by scanMemory()
*/
/**
* @typedef {number}
*/
var BlockInfo;
/**
* This defines the BlockInfo bit fields used by scanMemory() when it creates the aBlocks array.
*
* @typedef {{
* num: BitField,
* count: BitField,
* btmod: BitField,
* type: BitField
* }}
*/
Bus8080.BlockInfo = usr.defineBitFields({num:20, count:8, btmod:1, type:3});
/**
* BusInfo8080 object definition (returned by scanMemory())
*
* cbTotal: total bytes allocated
* cBlocks: total Memory blocks allocated
* aBlocks: array of allocated Memory block numbers
*
* @typedef {{
* cbTotal: number,
* cBlocks: number,
* aBlocks: Array.<BlockInfo>
* }}
*/
var BusInfo8080;
/**
* scanMemory(info, addr, size)
*

View file

@ -384,11 +384,11 @@ Memory8080.prototype = {
setReadAccess: function(afn, fDirect) {
if (!fDirect || !this.cReadBreakpoints) {
this.readByte = afn[0] || this.readNone;
this.readShort = afn[1] || this.readShortDefault;
this.readShort = afn[2] || this.readShortDefault;
}
if (fDirect || fDirect === undefined) {
this.readByteDirect = afn[0] || this.readNone;
this.readShortDirect = afn[1] || this.readShortDefault;
this.readShortDirect = afn[2] || this.readShortDefault;
}
},
/**
@ -400,11 +400,11 @@ Memory8080.prototype = {
*/
setWriteAccess: function(afn, fDirect) {
if (!fDirect || !this.cWriteBreakpoints) {
this.writeByte = !this.fReadOnly && afn[2] || this.writeNone;
this.writeByte = !this.fReadOnly && afn[1] || this.writeNone;
this.writeShort = !this.fReadOnly && afn[3] || this.writeShortDefault;
}
if (fDirect || fDirect === undefined) {
this.writeByteDirect = afn[2] || this.writeNone;
this.writeByteDirect = afn[1] || this.writeNone;
this.writeShortDirect = afn[3] || this.writeShortDefault;
}
},
@ -807,18 +807,45 @@ Memory8080.prototype = {
/*
* This is the effective definition of afnNone, but we need not fully define it, because setAccess()
* uses these defaults when any of the 6 handlers (ie, 3 read handlers and 3 write handlers) are undefined.
* uses these defaults when any of the 4 handlers (ie, 2 byte handlers and 2 short handlers) are undefined.
*
Memory8080.afnNone = [Memory8080.prototype.readNone, Memory8080.prototype.readShortDefault, Memory8080.prototype.writeNone, Memory8080.prototype.writeShortDefault];
Memory8080.afnNone = [
Memory8080.prototype.readNone,
Memory8080.prototype.writeNone,
Memory8080.prototype.readShortDefault,
Memory8080.prototype.writeShortDefault
];
*/
Memory8080.afnNone = [];
Memory8080.afnNone = [];
Memory8080.afnMemory = [Memory8080.prototype.readByteMemory, Memory8080.prototype.readShortMemory, Memory8080.prototype.writeByteMemory, Memory8080.prototype.writeShortMemory];
Memory8080.afnChecked = [Memory8080.prototype.readByteChecked, Memory8080.prototype.readShortChecked, Memory8080.prototype.writeByteChecked, Memory8080.prototype.writeShortChecked];
Memory8080.afnMemory = [
Memory8080.prototype.readByteMemory,
Memory8080.prototype.writeByteMemory,
Memory8080.prototype.readShortMemory,
Memory8080.prototype.writeShortMemory
];
Memory8080.afnChecked = [
Memory8080.prototype.readByteChecked,
Memory8080.prototype.writeByteChecked,
Memory8080.prototype.readShortChecked,
Memory8080.prototype.writeShortChecked
];
if (TYPEDARRAYS) {
Memory8080.afnArrayBE = [Memory8080.prototype.readByteBE, Memory8080.prototype.readShortBE, Memory8080.prototype.writeByteBE, Memory8080.prototype.writeShortBE];
Memory8080.afnArrayLE = [Memory8080.prototype.readByteLE, Memory8080.prototype.readShortLE, Memory8080.prototype.writeByteLE, Memory8080.prototype.writeShortLE];
Memory8080.afnArrayBE = [
Memory8080.prototype.readByteBE,
Memory8080.prototype.writeByteBE,
Memory8080.prototype.readShortBE,
Memory8080.prototype.writeShortBE
];
Memory8080.afnArrayLE = [
Memory8080.prototype.readByteLE,
Memory8080.prototype.writeByteLE,
Memory8080.prototype.readShortLE,
Memory8080.prototype.writeShortLE
];
}
if (NODE) module.exports = Memory8080;