Changed the primary means updating the PSW to setPSW(), and put some handcuffs on writePSW()
This commit is contained in:
parent
7b3a2cb676
commit
0e38c6dbc7
6 changed files with 378 additions and 357 deletions
|
|
@ -308,8 +308,8 @@ BusPDP11.prototype.initMemory = function()
|
|||
}
|
||||
this.afnIOPage = new Array(4);
|
||||
this.afnIOPage[0] = BusPDP11.controller.readIOPageByte;
|
||||
this.afnIOPage[1] = BusPDP11.controller.readIOPageShort;
|
||||
this.afnIOPage[2] = BusPDP11.controller.writeIOPageByte;
|
||||
this.afnIOPage[1] = BusPDP11.controller.writeIOPageByte;
|
||||
this.afnIOPage[2] = BusPDP11.controller.readIOPageShort;
|
||||
this.afnIOPage[3] = BusPDP11.controller.writeIOPageShort;
|
||||
this.addrIOPage = this.addrTotal - BusPDP11.IOPAGE_LENGTH;
|
||||
this.addMemory(this.addrIOPage, BusPDP11.IOPAGE_LENGTH, MemoryPDP11.TYPE.CONTROLLER, this);
|
||||
|
|
|
|||
|
|
@ -271,7 +271,7 @@ CPUStatePDP11.prototype.setBinding = function(sHTMLType, sBinding, control, sVal
|
|||
case "ZF":
|
||||
case "VF":
|
||||
case "CF":
|
||||
case "PSW":
|
||||
case "PS":
|
||||
this.bindings[sBinding] = control;
|
||||
this.cLiveRegs++;
|
||||
fBound = true;
|
||||
|
|
@ -300,7 +300,7 @@ CPUStatePDP11.prototype.updateStatus = function(fForce)
|
|||
this.displayValue('R'+i, this.regsGen[i]);
|
||||
}
|
||||
var regPSW = this.getPSW();
|
||||
this.displayValue("PSW", regPSW);
|
||||
this.displayValue("PS", regPSW);
|
||||
this.displayValue("NF", (regPSW & PDP11.PSW.NF)? 1 : 0, 1);
|
||||
this.displayValue("ZF", (regPSW & PDP11.PSW.ZF)? 1 : 0, 1);
|
||||
this.displayValue("VF", (regPSW & PDP11.PSW.VF)? 1 : 0, 1);
|
||||
|
|
@ -583,7 +583,19 @@ CPUStatePDP11.prototype.interrupt = function(delay, priority, vector, callback)
|
|||
};
|
||||
|
||||
/**
|
||||
* writePSW(newPSW)
|
||||
* readPSW()
|
||||
*
|
||||
* @this {CPUStatePDP11}
|
||||
* @return {number}
|
||||
*/
|
||||
CPUStatePDP11.prototype.readPSW = function()
|
||||
{
|
||||
var mask = PDP11.PSW.CMODE | PDP11.PSW.PMODE | PDP11.PSW.REGSET | PDP11.PSW.PRI | PDP11.PSW.TF;
|
||||
return this.PSW = (this.PSW & mask) | this.getNF() | this.getZF() | this.getVF() | this.getCF();
|
||||
};
|
||||
|
||||
/**
|
||||
* setPSW(newPSW)
|
||||
*
|
||||
* This updates the CPU Processor Status Word. The PSW should generally be written through
|
||||
* this routine so that changes can be tracked properly, for example the correct register set,
|
||||
|
|
@ -596,7 +608,7 @@ CPUStatePDP11.prototype.interrupt = function(delay, priority, vector, callback)
|
|||
* @this {CPUStatePDP11}
|
||||
* @param {number} newPSW
|
||||
*/
|
||||
CPUStatePDP11.prototype.writePSW = function(newPSW)
|
||||
CPUStatePDP11.prototype.setPSW = function(newPSW)
|
||||
{
|
||||
this.flagN = newPSW << 12;
|
||||
this.flagZ = (~newPSW) & 4;
|
||||
|
|
@ -629,15 +641,17 @@ CPUStatePDP11.prototype.writePSW = function(newPSW)
|
|||
};
|
||||
|
||||
/**
|
||||
* readPSW()
|
||||
* writePSW(newPSW)
|
||||
*
|
||||
* This is a stricter version of setPSW(), used for writes to ADDR_PSW, which preserves bits that
|
||||
* should not be overwritten.
|
||||
*
|
||||
* @this {CPUStatePDP11}
|
||||
* @return {number}
|
||||
* @param {number} newPSW
|
||||
*/
|
||||
CPUStatePDP11.prototype.readPSW = function()
|
||||
CPUStatePDP11.prototype.writePSW = function(newPSW)
|
||||
{
|
||||
var mask = PDP11.PSW.CMODE | PDP11.PSW.PMODE | PDP11.PSW.REGSET | PDP11.PSW.PRI | PDP11.PSW.TF;
|
||||
return this.PSW = (this.PSW & mask) | this.getNF() | this.getZF() | this.getVF() | this.getCF();
|
||||
this.setPSW((newPSW & 0xf8ef) | (this.PSW & 0x0710));
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -685,7 +699,7 @@ CPUStatePDP11.prototype.trap = function(vector, reason)
|
|||
this.mmuMode = 0; // read from kernel D space
|
||||
if ((newPC = this.readWordByVirtual(vector | 0x10000)) >= 0) {
|
||||
if ((newPSW = this.readWordByVirtual(((vector + 2) & 0xffff) | 0x10000)) >= 0) {
|
||||
this.writePSW((newPSW & 0xcfff) | ((this.trapPSW >> 2) & 0x3000)); // set new this.PSW with previous mode
|
||||
this.setPSW((newPSW & 0xcfff) | ((this.trapPSW >> 2) & 0x3000)); // set new this.PSW with previous mode
|
||||
if (doubleTrap) {
|
||||
this.CPU_Error |= 4;
|
||||
this.regsGen[6] = 4;
|
||||
|
|
@ -740,10 +754,10 @@ CPUStatePDP11.prototype.mapUnibus = function(unibusAddress)
|
|||
*
|
||||
* When doing mapping, mmuMode is used to decide what address space is to be
|
||||
* used. 0 = kernel, 1 = supervisor, 2 = illegal, 3 = user. Normally, mmuMode is
|
||||
* set by the writePSW() function but there are exceptions for instructions which
|
||||
* set by the setPSW() function but there are exceptions for instructions which
|
||||
* move data between address spaces (MFPD, MFPI, MTPD, and MTPI) and trap(). These will
|
||||
* modify mmuMode outside of writePSW() and then restore it again if all worked. If
|
||||
* however something happens to cause a trap then no restore is done as writePSW()
|
||||
* modify mmuMode outside of setPSW() and then restore it again if all worked. If
|
||||
* however something happens to cause a trap then no restore is done as setPSW()
|
||||
* will have been invoked as part of the trap, which will resynchronize mmuMode
|
||||
*
|
||||
* mmuMask[mmuMode] is used to control whether I/D space is active or not for
|
||||
|
|
@ -2188,7 +2202,7 @@ CPUStatePDP11.prototype.stepCPU = function(nMinCycles)
|
|||
//case 0106400: // MTPS 1064SS
|
||||
// //LOG_INSTRUCTION(instruction, 1, "MTPS");
|
||||
// if ((src = this.readByteByMode(instruction)) >= 0) {
|
||||
// this.writePSW((this.PSW & 0xff00) | (src & 0xef));
|
||||
// this.setPSW((this.PSW & 0xff00) | (src & 0xef));
|
||||
// } // Temporary PDP 11/34A
|
||||
// break;
|
||||
case 0x8D40: /*0106500*/ // MFPD 1065DD
|
||||
|
|
@ -2351,7 +2365,7 @@ CPUStatePDP11.prototype.stepCPU = function(nMinCycles)
|
|||
savePSW = (savePSW & 0xf81f) | (this.PSW & 0xf8e0);
|
||||
}
|
||||
this.regsGen[7] = virtualAddress;
|
||||
this.writePSW(savePSW);
|
||||
this.setPSW(savePSW);
|
||||
this.trapMask &= ~0x10; // turn off Trace trap
|
||||
if (instruction === 2) this.trapMask |= this.PSW & 0x10; // RTI enables immediate trace
|
||||
}
|
||||
|
|
|
|||
|
|
@ -205,7 +205,7 @@ DevicePDP11.prototype.initBus = function(cmp, bus, cpu, dbg)
|
|||
* readPSW(addr)
|
||||
*
|
||||
* @this {DevicePDP11}
|
||||
* @param {number} addr
|
||||
* @param {number} addr (ie, ADDR_PSW)
|
||||
* @return {number}
|
||||
*/
|
||||
DevicePDP11.prototype.readPSW = function(addr)
|
||||
|
|
@ -218,14 +218,19 @@ DevicePDP11.prototype.readPSW = function(addr)
|
|||
*
|
||||
* @this {DevicePDP11}
|
||||
* @param {number} data
|
||||
* @param {number} addr
|
||||
* @param {number} addr (ie, ADDR_PSW)
|
||||
*/
|
||||
DevicePDP11.prototype.writePSW = function(data, addr)
|
||||
{
|
||||
/*
|
||||
* TODO: Review the next line, which mimics access(), and determine if writePSW() can do this itself.
|
||||
* TODO: Determine whether we need to replicate the code in access_iopage() that returns a bogus
|
||||
* error when writing to ADDR_PSW, as a way of preventing instructions like CLR from updating the flags
|
||||
* and potentially modifying some of the PSW bits that were just set (eg, the Z flag).
|
||||
*
|
||||
* If so, then we'll need to centralize the flag update logic, so that it can be skipped whenever a
|
||||
* special one-time opcode flag is set. Because there are a number of arithmetic instructions besides
|
||||
* CLR that could be used to modify ADDR_PSW.
|
||||
*/
|
||||
data = (data & 0xf8ef) | (this.cpu.readPSW() & 0x0710);
|
||||
this.cpu.writePSW(data);
|
||||
};
|
||||
|
||||
|
|
@ -706,6 +711,40 @@ DevicePDP11.prototype.getCache = function(callback, meta, block, address, count)
|
|||
xhr.send(null);
|
||||
};
|
||||
|
||||
/**
|
||||
* insertData(original, physicalAddress, data, byteFlag)
|
||||
*
|
||||
* @this {DevicePDP11}
|
||||
* @param {number} original
|
||||
* @param {number} physicalAddress
|
||||
* @param {number} data
|
||||
* @param {number} byteFlag
|
||||
* @return {number}
|
||||
*/
|
||||
DevicePDP11.prototype.insertData = function(original, physicalAddress, data, byteFlag)
|
||||
{
|
||||
if (physicalAddress & 1) {
|
||||
if (!byteFlag) {
|
||||
//log.push("TRAP 4 201 " + physicalAddress.toString(8) + " " + data.toString(8));
|
||||
return this.cpu.trap(4, 122);
|
||||
}
|
||||
if (data >= 0) {
|
||||
data = ((data << 8) & 0xff00) | (original & 0xff);
|
||||
} else {
|
||||
data = original;
|
||||
}
|
||||
} else {
|
||||
if (data >= 0) {
|
||||
if (byteFlag) {
|
||||
data = (original & 0xff00) | (data & 0xff);
|
||||
}
|
||||
} else {
|
||||
data = original;
|
||||
}
|
||||
}
|
||||
return data;
|
||||
};
|
||||
|
||||
/**
|
||||
* readData(meta, block, address, count)
|
||||
*
|
||||
|
|
@ -810,8 +849,11 @@ DevicePDP11.prototype.access = function(physicalAddress, data, byteFlag)
|
|||
switch (physicalAddress & ~0x3F) /*077*/ {
|
||||
case 0x3FFFC0: /*017777700*/ // 017777700 - 017777777
|
||||
switch (physicalAddress & ~1) {
|
||||
case 0x3FFFFE: /*017777776*/ // PSW
|
||||
Component.assert(false); // verify that this is being handled by our new registered functions now
|
||||
/*
|
||||
* Superseded by UNIBUS_TABLE (much more of this code will be commented out
|
||||
* as it is replaced by read/write handlers in the UNIBUS_TABLE; stay tuned).
|
||||
*
|
||||
case 0x3FFFFE: // 017777776 // PSW
|
||||
result = cpu.readPSW();
|
||||
if (data >= 0) {
|
||||
if (physicalAddress & 1) {
|
||||
|
|
@ -819,11 +861,11 @@ DevicePDP11.prototype.access = function(physicalAddress, data, byteFlag)
|
|||
} else {
|
||||
if (byteFlag) data = (result & 0xff00) | (data & 0xff);
|
||||
}
|
||||
data = (data & 0xf8ef) | (result & 0x0710);
|
||||
cpu.writePSW(data);
|
||||
return -1; // KLUDGE - no trap but abort any CC updates
|
||||
}
|
||||
break;
|
||||
*/
|
||||
case 0x3FFFFC: /*017777774*/ // stack limit
|
||||
if (data < 0) {
|
||||
result = cpu.stackLimit & 0xff00;
|
||||
|
|
@ -1391,40 +1433,6 @@ DevicePDP11.prototype.access = function(physicalAddress, data, byteFlag)
|
|||
return result;
|
||||
};
|
||||
|
||||
/**
|
||||
* insertData(original, physicalAddress, data, byteFlag)
|
||||
*
|
||||
* @this {DevicePDP11}
|
||||
* @param {number} original
|
||||
* @param {number} physicalAddress
|
||||
* @param {number} data
|
||||
* @param {number} byteFlag
|
||||
* @return {number}
|
||||
*/
|
||||
DevicePDP11.prototype.insertData = function(original, physicalAddress, data, byteFlag)
|
||||
{
|
||||
if (physicalAddress & 1) {
|
||||
if (!byteFlag) {
|
||||
//log.push("TRAP 4 201 " + physicalAddress.toString(8) + " " + data.toString(8));
|
||||
return this.cpu.trap(4, 122);
|
||||
}
|
||||
if (data >= 0) {
|
||||
data = ((data << 8) & 0xff00) | (original & 0xff);
|
||||
} else {
|
||||
data = original;
|
||||
}
|
||||
} else {
|
||||
if (data >= 0) {
|
||||
if (byteFlag) {
|
||||
data = (original & 0xff00) | (data & 0xff);
|
||||
}
|
||||
} else {
|
||||
data = original;
|
||||
}
|
||||
}
|
||||
return data;
|
||||
};
|
||||
|
||||
DevicePDP11.UNIBUS_TABLE = {};
|
||||
DevicePDP11.UNIBUS_TABLE[DevicePDP11.ADDR_PSW] = [null, null, DevicePDP11.prototype.readPSW, DevicePDP11.prototype.writePSW];
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue