Laying the groundwork for an attempt at PDP-11 cycle counting (it won't be exact, but it should be close)

This commit is contained in:
Jeff 2016-09-30 12:00:07 -07:00 committed by Jeff Parsons
commit af6b66d2a3
4 changed files with 221 additions and 193 deletions

View file

@ -468,7 +468,7 @@ PDP11.opADCB = function(opCode)
PDP11.opADD = function(opCode)
{
this.updateWordByMode(opCode, this.readWordByMode(opCode >> PDP11.SRCMODE.SHIFT), PDP11.fnADD);
this.nStepCycles -= 1;
this.nStepCycles -= (this.dstMode? (8 + 1) + (this.srcReg && this.dstReg >= 6? 1 : 0) : (this.srcMode? (3 + 2) : (2 + 1) + (this.dstReg == 7? 2 : 0)));
};
/**

View file

@ -165,7 +165,19 @@ CPUStatePDP11.prototype.initRegs = function()
this.controlReg = [ // various control registers we don't really care about
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
];
/*
* opFlags contains various triggers that stepCPU() needs to be aware of
*/
this.opFlags = 0;
/*
* srcMode and dstMode are set by getVirtualByMode(), indicating to the opcode handlers the mode(s) used
* as part of the current opcode. Ditto for srcReg and dstReg.
*/
this.srcMode = this.dstMode = 0;
this.srcReg = this.dstReg = 0;
this.cpuType = 70;
this.trapPSW = -1;
this.loopRate = 9999; // instructions we can execute in 12ms
@ -1214,6 +1226,7 @@ CPUStatePDP11.prototype.readByteFromPhysical = function(physicalAddress)
*/
CPUStatePDP11.prototype.writeByteToPhysical = function(physicalAddress, data)
{
if (physicalAddress & 1) this.nStepCycles--;
this.bus.setByte(physicalAddress, data & 0xff);
};
@ -1293,17 +1306,29 @@ CPUStatePDP11.prototype.pushWord = function(data)
*/
CPUStatePDP11.prototype.getVirtualByMode = function(addressMode, accessFlags)
{
var virtualAddress, stepSize, reg = addressMode & 7;
var virtualAddress, stepSize;
var addrDSpace = (accessFlags & PDP11.ACCESS.VIRT)? 0 : this.addrDSpace;
switch ((addressMode >> 3) & 7) {
var reg = addressMode & 7;
var mode = (addressMode >> 3) & 7;
if (accessFlags & PDP11.ACCESS.WRITE) {
this.dstMode = mode; this.dstReg = reg;
} else {
this.srcMode = mode; this.srcReg = reg;
}
/*
* Modes that need to auto-increment or auto-decrement will break,
* n order to perform the update; others will return an address immediately.
*/
switch (mode) {
/*
* Mode 0: Registers don't have a virtual address so trap
*/
case 0:
this.trap(PDP11.TRAP.BUS_ERROR, PDP11.REASON.NOREGADDR);
break;
return 0;
/*
* Mode 1: (R)
@ -1320,7 +1345,8 @@ CPUStatePDP11.prototype.getVirtualByMode = function(addressMode, accessFlags)
this.opFlags |= PDP11.OPFLAG.TRAP_SP;
}
}
return (reg === 7 ? this.regsGen[reg] : (this.regsGen[reg] | addrDSpace));
this.nStepCycles -= 2 + 1;
return (reg === 7? this.regsGen[reg] : (this.regsGen[reg] | addrDSpace));
/*
* Mode 2: (R)+
@ -1334,6 +1360,7 @@ CPUStatePDP11.prototype.getVirtualByMode = function(addressMode, accessFlags)
stepSize = 1;
}
}
this.nStepCycles -= 2 + 1;
break;
/*
@ -1346,6 +1373,7 @@ CPUStatePDP11.prototype.getVirtualByMode = function(addressMode, accessFlags)
virtualAddress = this.readWordFromVirtual(virtualAddress);
// if (reg === 7) LOG_ADDRESS(virtualAddress); // @#n not operational
virtualAddress |= addrDSpace;
this.nStepCycles -= 5 + 2;
break;
/*
@ -1355,9 +1383,8 @@ CPUStatePDP11.prototype.getVirtualByMode = function(addressMode, accessFlags)
stepSize = -2;
if (reg < 6 && (accessFlags & PDP11.ACCESS.BYTE)) stepSize = -1;
virtualAddress = (this.regsGen[reg] + stepSize) & 0xffff;
if (reg !== 7) {
virtualAddress |= addrDSpace;
}
if (reg !== 7) virtualAddress |= addrDSpace;
this.nStepCycles -= 3 + 1;
break;
/*
@ -1368,6 +1395,7 @@ CPUStatePDP11.prototype.getVirtualByMode = function(addressMode, accessFlags)
virtualAddress = (this.regsGen[reg] - 2) & 0xffff;
if (reg !== 7) virtualAddress |= addrDSpace;
virtualAddress = this.readWordFromVirtual(virtualAddress) | addrDSpace;
this.nStepCycles -= 6 + 2;
break;
/*
@ -1376,6 +1404,7 @@ CPUStatePDP11.prototype.getVirtualByMode = function(addressMode, accessFlags)
case 6:
virtualAddress = this.getPCWord();
virtualAddress = ((virtualAddress + this.regsGen[reg]) & 0xffff) | addrDSpace;
this.nStepCycles -= 4 + 2;
return virtualAddress;
/*
@ -1385,6 +1414,7 @@ CPUStatePDP11.prototype.getVirtualByMode = function(addressMode, accessFlags)
virtualAddress = this.getPCWord();
virtualAddress = (virtualAddress + this.regsGen[reg]) & 0xffff;
virtualAddress = this.readWordFromVirtual(virtualAddress | PDP11.ACCESS.DSPACE) | addrDSpace;
this.nStepCycles -= 7 + 3;
return virtualAddress;
}
@ -1454,7 +1484,7 @@ CPUStatePDP11.prototype.readWordFromPrevSpace = function(opCode, accessFlags)
src = this.regsAltStack[(this.regPSW >> 12) & 3];
}
} else {
var addr = this.getVirtualByMode(opCode, PDP11.ACCESS.WORD);
var addr = this.getVirtualByMode(opCode, PDP11.ACCESS.READ_WORD);
if (!(accessFlags & PDP11.ACCESS.DSPACE)) {
if ((this.regPSW & 0xf000) !== 0xf000) addr &= 0xffff;
}
@ -1472,7 +1502,6 @@ CPUStatePDP11.prototype.readWordFromPrevSpace = function(opCode, accessFlags)
* @param {number} opCode
* @param {number} accessFlags (really just PDP11.ACCESS.DSPACE or PDP11.ACCESS.ISPACE)
* @param {number} data
* @return {number}
*/
CPUStatePDP11.prototype.writeWordToPrevSpace = function(opCode, accessFlags, data)
{
@ -1487,14 +1516,13 @@ CPUStatePDP11.prototype.writeWordToPrevSpace = function(opCode, accessFlags, dat
this.regsAltStack[(this.regPSW >> 12) & 3] = data;
}
} else {
var addr = this.getVirtualByMode(opCode, PDP11.ACCESS.WORD);
var addr = this.getVirtualByMode(opCode, PDP11.ACCESS.WRITE_WORD);
if (!(accessFlags & PDP11.ACCESS.DSPACE)) addr &= 0xffff;
this.mmuMode = (this.regPSW >> 12) & 3;
addr = this.mapVirtualToPhysical(addr | (accessFlags & PDP11.ACCESS.DSPACE), PDP11.ACCESS.WRITE);
this.mmuMode = (this.regPSW >> 14) & 3;
this.writeWordToPhysical(addr, data);
}
return data;
};
/**