More cleanup of RED stack overflow handling

This commit is contained in:
Jeff Parsons 2016-11-19 16:42:52 -08:00 committed by Jeff Parsons
commit 687439e57e
5 changed files with 201 additions and 208 deletions

View file

@ -125,10 +125,10 @@ CPUStatePDP11.prototype.initProcessor = function()
{
if (this.model == PDP11.MODEL_1120) {
this.decode = PDP11.op1120.bind(this);
this.checkStackLimit = this.checkStackLimitOld;
this.checkStackLimit = this.checkStackLimit1120;
} else {
this.decode = PDP11.op1145.bind(this);
this.checkStackLimit = this.checkStackLimitNew;
this.checkStackLimit = this.checkStackLimit1145;
}
this.initRegs();
@ -1306,9 +1306,11 @@ CPUStatePDP11.prototype.trap = function(vector, flag, reason)
if (this.trapPSW < 0) {
this.trapPSW = this.getPSW();
} else if (!this.mmuMode) {
/*
* Double-fault (nested trap) condition detected.
*/
reason = PDP11.REASON.RED; // double-fault (nested trap) forces a RED condition
}
var fRed = false;
if (reason == PDP11.REASON.RED) {
vector = 4;
/*
* The next two lines used to be deferred until after the setPSW() below, but
@ -1316,7 +1318,7 @@ CPUStatePDP11.prototype.trap = function(vector, flag, reason)
*/
this.regErr |= PDP11.CPUERR.RED;
this.regsGen[6] = 4;
reason = PDP11.REASON.RED;
fRed = true;
}
/*
@ -1345,8 +1347,8 @@ CPUStatePDP11.prototype.trap = function(vector, flag, reason)
*/
this.setPSW((newPSW & ~PDP11.PSW.PMODE) | ((this.trapPSW >> 2) & PDP11.PSW.PMODE));
this.pushWord(this.trapPSW);
this.pushWord(this.regsGen[7]);
this.pushWord(this.trapPSW, fRed);
this.pushWord(this.regsGen[7], fRed);
this.setPC(newPC);
/*
@ -1730,17 +1732,18 @@ CPUStatePDP11.prototype.popWord = function()
};
/**
* pushWord(data)
* pushWord(data, fRed)
*
* @this {CPUStatePDP11}
* @param {number} data
* @param {boolean} [fRed]
*/
CPUStatePDP11.prototype.pushWord = function(data)
CPUStatePDP11.prototype.pushWord = function(data, fRed)
{
var virtualAddress = (this.regsGen[6] - 2) & 0xffff;
this.regsGen[6] = virtualAddress; // BSD needs SP updated before any fault :-(
this.lastOp = (this.lastOp & 0xffff) | ((this.lastOp & ~0xffff) << 8) | (0x00f6 << 16);
this.checkStackLimit(PDP11.ACCESS.PUSH_WORD, -2, virtualAddress);
if (!fRed) this.checkStackLimit(PDP11.ACCESS.WRITE_WORD, -2, virtualAddress);
this.writeWord(virtualAddress, data);
};
@ -1890,14 +1893,14 @@ CPUStatePDP11.prototype.getAddrByMode = function(mode, reg, access)
};
/**
* checkStackLimitOld(access, step, addr)
* checkStackLimit1120(access, step, addr)
*
* @this {CPUStatePDP11}
* @param {number} access
* @param {number} step
* @param {number} addr
*/
CPUStatePDP11.prototype.checkStackLimitOld = function(access, step, addr)
CPUStatePDP11.prototype.checkStackLimit1120 = function(access, step, addr)
{
/*
* NOTE: DEC's "TRAP TEST" (MAINDEC-11-D0NA-PB) expects "TST -(SP)" to trap when SP is 150,
@ -1920,31 +1923,22 @@ CPUStatePDP11.prototype.checkStackLimitOld = function(access, step, addr)
};
/**
* checkStackLimitNew(access, step, addr)
* checkStackLimit1145(access, step, addr)
*
* @this {CPUStatePDP11}
* @param {number} access
* @param {number} step
* @param {number} addr
*/
CPUStatePDP11.prototype.checkStackLimitNew = function(access, step, addr)
CPUStatePDP11.prototype.checkStackLimit1145 = function(access, step, addr)
{
if (!this.mmuMode) {
/*
* NOTE: The 11/70 CPU Instruction Exerciser does NOT expect reads to trigger a stack overflow, so we
* check the access parameter.
*
* The special PUSH_WORD case used by pushWord() ignores addr <= 4, because pushWord() is used by trap(),
* and if the trap() was generated by a RED error (below) or generated a RED error itself, then we need to
* avoid triggering another (nested) RED error.
* NOTE: The 11/70 CPU Instruction Exerciser does NOT expect reads to trigger a stack overflow,
* so we check the access parameter.
*/
if (!(access & PDP11.ACCESS.WRITE) || access == PDP11.ACCESS.PUSH_WORD && addr <= 4) {
return;
}
if (addr <= this.regSL) {
if ((access & PDP11.ACCESS.WRITE) && addr <= this.regSL) {
if (addr <= this.regSL - 32) {
this.regErr |= PDP11.CPUERR.RED;
this.regsGen[6] = 4;
this.trap(PDP11.TRAP.BUS, 0, PDP11.REASON.RED);
} else {
this.regErr |= PDP11.CPUERR.YELLOW;

View file

@ -307,7 +307,6 @@ var PDP11 = {
WRITE: 0x04,
UPDATE: 0x06,
VIRT: 0x08, // getVirtualByMode() leaves bit 17 clear if this is set (otherwise the caller would have to clear it again)
PUSH: 0x10,
ISPACE: 0x00000,
DSPACE: 0x10000 // getVirtualByMode() sets bit 17 in any 16-bit virtual address that refers to D space (as opposed to I space)
},
@ -748,7 +747,6 @@ PDP11.ACCESS.WRITE_WORD = PDP11.ACCESS.WORD | PDP11.ACCESS.WRITE; // forme
PDP11.ACCESS.WRITE_BYTE = PDP11.ACCESS.BYTE | PDP11.ACCESS.WRITE; // formerly WRITE_MODE (4) | BYTE_MODE (1)
PDP11.ACCESS.UPDATE_WORD = PDP11.ACCESS.WORD | PDP11.ACCESS.UPDATE; // formerly MODIFY_WORD (2 | 4)
PDP11.ACCESS.UPDATE_BYTE = PDP11.ACCESS.BYTE | PDP11.ACCESS.UPDATE; // formerly MODIFY_BYTE (1 | 2 | 4)
PDP11.ACCESS.PUSH_WORD = PDP11.ACCESS.WORD | PDP11.ACCESS.WRITE | PDP11.ACCESS.PUSH;
/*
* PSW arithmetic flags are NOT stored directly into the PSW register; they are maintained across separate