More cleanup of RED stack overflow handling
This commit is contained in:
parent
eb9c372043
commit
687439e57e
5 changed files with 201 additions and 208 deletions
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Reference in a new issue