More PDP-11 debugger work
This commit is contained in:
parent
6f349612d8
commit
cc70c05c07
6 changed files with 545 additions and 456 deletions
|
|
@ -131,13 +131,13 @@ CPUStatePDP11.prototype.initRegs = function()
|
|||
this.flagV = 0x8000; // PSW V bit
|
||||
this.flagZ = 0xffff; // ~ PSW Z bit
|
||||
this.PSW = 0xf; // PSW other bits
|
||||
this.regsCur = [ // Current R0 - R7
|
||||
this.regsGen = [ // General R0 - R7
|
||||
0, 0, 0, 0, 0, 0, 0, 0
|
||||
];
|
||||
this.regsAlt = [ // Alternate R0 - R5
|
||||
0, 0, 0, 0, 0, 0
|
||||
];
|
||||
this.regsStack = [ // Alternate R6 (kernel, super, illegal, user)
|
||||
this.regsAltStack = [ // Alternate R6 (kernel, super, illegal, user)
|
||||
0, 0, 0, 0
|
||||
];
|
||||
this.memory = []; // Main memory (words)
|
||||
|
|
@ -258,8 +258,9 @@ CPUStatePDP11.prototype.setBinding = function(sHTMLType, sBinding, control, sVal
|
|||
switch (sBinding) {
|
||||
case "PC":
|
||||
case "PSW":
|
||||
case "SF":
|
||||
case "NF":
|
||||
case "ZF":
|
||||
case "VF":
|
||||
case "CF":
|
||||
this.bindings[sBinding] = control;
|
||||
this.cLiveRegs++;
|
||||
|
|
@ -279,18 +280,18 @@ CPUStatePDP11.prototype.setBinding = function(sHTMLType, sBinding, control, sVal
|
|||
*/
|
||||
CPUStatePDP11.prototype.clearCF = function()
|
||||
{
|
||||
this.resultZeroCarry &= 0xff;
|
||||
// this.resultZeroCarry &= 0xff;
|
||||
};
|
||||
|
||||
/**
|
||||
* getCF()
|
||||
*
|
||||
* @this {CPUStatePDP11}
|
||||
* @return {number} 0 or 1 (PDP11.PSW.CF)
|
||||
* @return {number} 0 or PDP11.PSW.CF
|
||||
*/
|
||||
CPUStatePDP11.prototype.getCF = function()
|
||||
{
|
||||
return (this.resultZeroCarry & 0x100)? PDP11.PSW.CF : 0;
|
||||
return (this.flagC & 0x10000)? PDP11.PSW.CF: 0;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -300,18 +301,38 @@ CPUStatePDP11.prototype.getCF = function()
|
|||
*/
|
||||
CPUStatePDP11.prototype.setCF = function()
|
||||
{
|
||||
this.resultZeroCarry |= 0x100;
|
||||
// this.resultZeroCarry |= 0x100;
|
||||
};
|
||||
|
||||
/**
|
||||
* updateCF(CF)
|
||||
* clearVF()
|
||||
*
|
||||
* @this {CPUStatePDP11}
|
||||
* @param {number} CF (0x000 or 0x100)
|
||||
*/
|
||||
CPUStatePDP11.prototype.updateCF = function(CF)
|
||||
CPUStatePDP11.prototype.clearVF = function()
|
||||
{
|
||||
this.resultZeroCarry = (this.resultZeroCarry & 0xff) | CF;
|
||||
// this.resultZeroCarry |= 0xff;
|
||||
};
|
||||
|
||||
/**
|
||||
* getVF()
|
||||
*
|
||||
* @this {CPUStatePDP11}
|
||||
* @return {number} 0 or PDP11.PSW.VF
|
||||
*/
|
||||
CPUStatePDP11.prototype.getVF = function()
|
||||
{
|
||||
return (this.flagV & 0x8000)? PDP11.PSW.VF: 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* setVF()
|
||||
*
|
||||
* @this {CPUStatePDP11}
|
||||
*/
|
||||
CPUStatePDP11.prototype.setVF = function()
|
||||
{
|
||||
// this.resultZeroCarry &= ~0xff;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -321,7 +342,7 @@ CPUStatePDP11.prototype.updateCF = function(CF)
|
|||
*/
|
||||
CPUStatePDP11.prototype.clearZF = function()
|
||||
{
|
||||
this.resultZeroCarry |= 0xff;
|
||||
// this.resultZeroCarry |= 0xff;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -332,7 +353,7 @@ CPUStatePDP11.prototype.clearZF = function()
|
|||
*/
|
||||
CPUStatePDP11.prototype.getZF = function()
|
||||
{
|
||||
return (this.resultZeroCarry & 0xff)? 0 : PDP11.PSW.ZF;
|
||||
return (this.flagZ & 0xffff)? 0 : PDP11.PSW.ZF;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -342,39 +363,38 @@ CPUStatePDP11.prototype.getZF = function()
|
|||
*/
|
||||
CPUStatePDP11.prototype.setZF = function()
|
||||
{
|
||||
this.resultZeroCarry &= ~0xff;
|
||||
// this.resultZeroCarry &= ~0xff;
|
||||
};
|
||||
|
||||
/**
|
||||
* clearSF()
|
||||
* clearNF()
|
||||
*
|
||||
* @this {CPUStatePDP11}
|
||||
*/
|
||||
CPUStatePDP11.prototype.clearSF = function()
|
||||
CPUStatePDP11.prototype.clearNF = function()
|
||||
{
|
||||
// if (this.getSF()) this.resultParitySign ^= 0xc0;
|
||||
// if (this.getNF()) this.resultParitySign ^= 0xc0;
|
||||
};
|
||||
|
||||
/**
|
||||
* getSF()
|
||||
* getNF()
|
||||
*
|
||||
* @this {CPUStatePDP11}
|
||||
* @return {number} 0 or PDP11.PSW.SF
|
||||
* @return {number} 0 or PDP11.PSW.NF
|
||||
*/
|
||||
CPUStatePDP11.prototype.getSF = function()
|
||||
CPUStatePDP11.prototype.getNF = function()
|
||||
{
|
||||
// return (this.resultParitySign & 0x80)? PDP11.PSW.SF : 0;
|
||||
return 0;
|
||||
return (this.flagN >> (15 - PDP11.PSW.NF_SHIFT)) & PDP11.PSW.NF;
|
||||
};
|
||||
|
||||
/**
|
||||
* setSF()
|
||||
* setNF()
|
||||
*
|
||||
* @this {CPUStatePDP11}
|
||||
*/
|
||||
CPUStatePDP11.prototype.setSF = function()
|
||||
CPUStatePDP11.prototype.setNF = function()
|
||||
{
|
||||
// if (!this.getSF()) this.resultParitySign ^= 0xc0;
|
||||
// if (!this.getNF()) this.resultParitySign ^= 0xc0;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -385,7 +405,7 @@ CPUStatePDP11.prototype.setSF = function()
|
|||
*/
|
||||
CPUStatePDP11.prototype.getPC = function()
|
||||
{
|
||||
return this.regsCur[7];
|
||||
return this.regsGen[7];
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -396,7 +416,7 @@ CPUStatePDP11.prototype.getPC = function()
|
|||
*/
|
||||
CPUStatePDP11.prototype.setPC = function(addr)
|
||||
{
|
||||
this.regsCur[7] = addr;
|
||||
this.regsGen[7] = addr;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -407,7 +427,7 @@ CPUStatePDP11.prototype.setPC = function(addr)
|
|||
*/
|
||||
CPUStatePDP11.prototype.getPSW = function()
|
||||
{
|
||||
return (this.PSW & ~PDP11.PSW.RESULT) | (this.getSF() | this.getZF() | this.getCF());
|
||||
return (this.PSW & ~PDP11.PSW.FLAGS) | (this.getNF() | this.getZF() | this.getVF() | this.getCF());
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -418,7 +438,7 @@ CPUStatePDP11.prototype.getPSW = function()
|
|||
*/
|
||||
CPUStatePDP11.prototype.getSP = function()
|
||||
{
|
||||
return this.regsCur[6];
|
||||
return this.regsGen[6];
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -481,11 +501,11 @@ CPUStatePDP11.prototype.requestHALT = function()
|
|||
* @this {CPUStatePDP11}
|
||||
* @param {string} sReg
|
||||
* @param {number} nValue
|
||||
* @param {number} [cch] (default is 2 hex digits)
|
||||
* @param {number} [cch] (default is 4 hex digits)
|
||||
*/
|
||||
CPUStatePDP11.prototype.updateReg = function(sReg, nValue, cch)
|
||||
{
|
||||
this.displayValue(sReg, nValue, cch || 2);
|
||||
this.displayValue(sReg, nValue, cch || 4);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -503,8 +523,9 @@ CPUStatePDP11.prototype.updateStatus = function(fForce)
|
|||
if (fForce || !this.flags.running || this.flags.displayLiveRegs) {
|
||||
var regPSW = this.getPSW();
|
||||
this.updateReg("PSW", regPSW, 4);
|
||||
this.updateReg("SF", (regPSW & PDP11.PSW.SF)? 1 : 0, 1);
|
||||
this.updateReg("NF", (regPSW & PDP11.PSW.NF)? 1 : 0, 1);
|
||||
this.updateReg("ZF", (regPSW & PDP11.PSW.ZF)? 1 : 0, 1);
|
||||
this.updateReg("VF", (regPSW & PDP11.PSW.VF)? 1 : 0, 1);
|
||||
this.updateReg("CF", (regPSW & PDP11.PSW.CF)? 1 : 0, 1);
|
||||
}
|
||||
}
|
||||
|
|
@ -568,38 +589,46 @@ CPUStatePDP11.prototype.interrupt = function(delay, priority, vector, callback)
|
|||
/**
|
||||
* writePSW(newPSW)
|
||||
*
|
||||
* writePSW() is used to update 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, the current memory management mode, etc. An exception is
|
||||
* SPL which writes the priority directly. Note that that N, Z, V, and C flags are
|
||||
* actually stored separately to the PSW property for performance reasons.
|
||||
* 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,
|
||||
* the current memory management mode, etc. An exception is SPL which writes the priority directly.
|
||||
* Note that that N, Z, V, and C flags are actually stored separately for performance reasons.
|
||||
*
|
||||
* PSW 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
|
||||
* CM | PM |RS| |PRIORITY| T| N| Z| V| C
|
||||
* mode 0 kernel 1 super 3 user
|
||||
* CMODE PMODE RS -------- PRIORITY T N Z V C
|
||||
*
|
||||
* @this {CPUStatePDP11}
|
||||
* @param {number} newPSW
|
||||
*/
|
||||
CPUStatePDP11.prototype.writePSW = function(newPSW)
|
||||
{
|
||||
var i, j;
|
||||
this.flagN = newPSW << 12;
|
||||
this.flagZ = (~newPSW) & 4;
|
||||
this.flagV = newPSW << 14;
|
||||
this.flagC = newPSW << 16;
|
||||
if ((newPSW ^ this.PSW) & 0x800) {
|
||||
for (i = 0; i < 6; i++) {
|
||||
j = this.regsCur[i];
|
||||
this.regsCur[i] = this.regsAlt[i];
|
||||
this.regsAlt[i] = j; // swap to alternate register set
|
||||
if ((newPSW ^ this.PSW) & PDP11.PSW.REGSET) {
|
||||
/*
|
||||
* Swap register sets
|
||||
*/
|
||||
for (var i = this.regsAlt.length; --i >= 0;) {
|
||||
var tmp = this.regsGen[i];
|
||||
this.regsGen[i] = this.regsAlt[i];
|
||||
this.regsAlt[i] = tmp;
|
||||
}
|
||||
}
|
||||
if ((this.mmuMode = (newPSW >> 14) & 3) !== ((this.PSW >> 14) & 3)) {
|
||||
this.regsStack[j] = this.regsCur[6];
|
||||
this.regsCur[6] = this.regsStack[this.mmuMode]; // swap to new mode SP
|
||||
this.mmuMode = (newPSW >> PDP11.PSW.CMODE_SHIFT) & PDP11.MODE.MASK;
|
||||
var oldMode = (this.PSW >> PDP11.PSW.CMODE_SHIFT) & PDP11.MODE.MASK;
|
||||
if (this.mmuMode != oldMode) {
|
||||
/*
|
||||
* Swap stack pointers
|
||||
*/
|
||||
this.regsAltStack[oldMode] = this.regsGen[6];
|
||||
this.regsGen[6] = this.regsAltStack[this.mmuMode];
|
||||
}
|
||||
this.priorityReview = 2; // trigger check of priority levels
|
||||
/*
|
||||
* Trigger check of priority levels
|
||||
*/
|
||||
this.priorityReview = 2;
|
||||
this.PSW = newPSW;
|
||||
};
|
||||
|
||||
|
|
@ -611,9 +640,8 @@ CPUStatePDP11.prototype.writePSW = function(newPSW)
|
|||
*/
|
||||
CPUStatePDP11.prototype.readPSW = function()
|
||||
{
|
||||
this.PSW = (this.PSW & 0xf8f0) | ((this.flagN >> 12) & 8) | ((this.flagV >> 14) & 2) | ((this.flagC >> 16) & 1);
|
||||
if (!(this.flagZ & 0xffff)) this.PSW |= 4;
|
||||
return this.PSW;
|
||||
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();
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -663,10 +691,10 @@ CPUStatePDP11.prototype.trap = function(vector, reason)
|
|||
this.writePSW((newPSW & 0xcfff) | ((this.trapPSW >> 2) & 0x3000)); // set new this.PSW with previous mode
|
||||
if (doubleTrap) {
|
||||
this.CPU_Error |= 4;
|
||||
this.regsCur[6] = 4;
|
||||
this.regsGen[6] = 4;
|
||||
}
|
||||
if (this.pushWord(this.trapPSW) >= 0 && this.pushWord(this.regsCur[7]) >= 0) {
|
||||
this.regsCur[7] = newPC;
|
||||
if (this.pushWord(this.trapPSW) >= 0 && this.pushWord(this.regsGen[7]) >= 0) {
|
||||
this.regsGen[7] = newPC;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -860,7 +888,7 @@ CPUStatePDP11.prototype.mapVirtualToPhysical = function(virtualAddress, accessMa
|
|||
CPUStatePDP11.prototype.readWordByAddr = function(physicalAddress)
|
||||
{
|
||||
if (physicalAddress >= PDP11.MAX_ADDRESS) {
|
||||
return this.regsCur[physicalAddress - PDP11.MAX_ADDRESS];
|
||||
return this.regsGen[physicalAddress - PDP11.MAX_ADDRESS];
|
||||
} else {
|
||||
if (physicalAddress >= PDP11.IOBASE_UNIBUS) {
|
||||
return this.bus.access_iopage(physicalAddress, -1, 0);
|
||||
|
|
@ -885,7 +913,7 @@ CPUStatePDP11.prototype.writeWordByAddr = function(physicalAddress, data)
|
|||
{
|
||||
data &= 0xffff;
|
||||
if (physicalAddress >= PDP11.MAX_ADDRESS) {
|
||||
return (this.regsCur[physicalAddress - PDP11.MAX_ADDRESS] = data);
|
||||
return (this.regsGen[physicalAddress - PDP11.MAX_ADDRESS] = data);
|
||||
} else {
|
||||
if (physicalAddress >= PDP11.IOBASE_UNIBUS) {
|
||||
return this.bus.access_iopage(physicalAddress, data, 0);
|
||||
|
|
@ -909,7 +937,7 @@ CPUStatePDP11.prototype.readByteByAddr = function(physicalAddress)
|
|||
{
|
||||
var result;
|
||||
if (physicalAddress >= PDP11.MAX_ADDRESS) {
|
||||
return (this.regsCur[physicalAddress - PDP11.MAX_ADDRESS] & 0xff);
|
||||
return (this.regsGen[physicalAddress - PDP11.MAX_ADDRESS] & 0xff);
|
||||
} else {
|
||||
if (physicalAddress >= PDP11.IOBASE_UNIBUS) {
|
||||
return this.bus.access_iopage(physicalAddress, -1, 1);
|
||||
|
|
@ -938,7 +966,7 @@ CPUStatePDP11.prototype.writeByteByAddr = function(physicalAddress, data)
|
|||
{
|
||||
data &= 0xff;
|
||||
if (physicalAddress >= PDP11.MAX_ADDRESS) {
|
||||
return (this.regsCur[physicalAddress - PDP11.MAX_ADDRESS] = (this.regsCur[physicalAddress - PDP11.MAX_ADDRESS] & 0xff00) | data);
|
||||
return (this.regsGen[physicalAddress - PDP11.MAX_ADDRESS] = (this.regsGen[physicalAddress - PDP11.MAX_ADDRESS] & 0xff00) | data);
|
||||
} else {
|
||||
if (physicalAddress >= PDP11.IOBASE_UNIBUS) {
|
||||
return this.bus.access_iopage(physicalAddress, data, 1);
|
||||
|
|
@ -974,9 +1002,9 @@ CPUStatePDP11.prototype.readWordByVirtual = function(virtualAddress)
|
|||
*/
|
||||
CPUStatePDP11.prototype.popWord = function()
|
||||
{
|
||||
var result = this.readWordByVirtual(this.regsCur[6] | 0x10000);
|
||||
var result = this.readWordByVirtual(this.regsGen[6] | 0x10000);
|
||||
if (result >= 0) {
|
||||
this.regsCur[6] = (this.regsCur[6] + 2) & 0xffff;
|
||||
this.regsGen[6] = (this.regsGen[6] + 2) & 0xffff;
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
|
@ -991,14 +1019,14 @@ CPUStatePDP11.prototype.popWord = function()
|
|||
CPUStatePDP11.prototype.pushWord = function(data)
|
||||
{
|
||||
var physicalAddress, virtualAddress;
|
||||
this.regsCur[6] = virtualAddress = (this.regsCur[6] - 2) & 0xffff; // BSD needs SP updated before any fault :-(
|
||||
this.regsGen[6] = virtualAddress = (this.regsGen[6] - 2) & 0xffff; // BSD needs SP updated before any fault :-(
|
||||
if (!(this.MMR0 & 0xe000)) {
|
||||
this.MMR1 = (this.MMR1 << 8) | 0xf6;
|
||||
}
|
||||
if ((!this.mmuMode) && virtualAddress <= this.stackLimit && virtualAddress > 4) {
|
||||
if (virtualAddress <= this.stackLimit - 32) {
|
||||
this.CPU_Error |= 4; // Red stack
|
||||
this.regsCur[6] = 4;
|
||||
this.regsGen[6] = 4;
|
||||
return this.trap(4, 32);
|
||||
}
|
||||
this.CPU_Error |= 8; // Yellow
|
||||
|
|
@ -1048,19 +1076,19 @@ CPUStatePDP11.prototype.getVirtualByMode = function(addressMode, accessMode)
|
|||
return this.trap(4, 34); // trap for invalid virtual address
|
||||
case 1: // Mode 1: (R)
|
||||
if (reg === 6 && (!this.mmuMode) && (accessMode & PDP11.WRITE_MODE) &&
|
||||
(this.regsCur[6] <= this.stackLimit || this.regsCur[6] >= 0xfffe)) {
|
||||
if (this.regsCur[6] <= this.stackLimit - 32 || this.regsCur[6] >= 0xfffe) {
|
||||
(this.regsGen[6] <= this.stackLimit || this.regsGen[6] >= 0xfffe)) {
|
||||
if (this.regsGen[6] <= this.stackLimit - 32 || this.regsGen[6] >= 0xfffe) {
|
||||
this.CPU_Error |= 4; // Red stack
|
||||
this.regsCur[6] = 4;
|
||||
this.regsGen[6] = 4;
|
||||
return this.trap(4, 36);
|
||||
}
|
||||
this.CPU_Error |= 8; // Yellow
|
||||
this.trapMask |= 4;
|
||||
}
|
||||
return (reg === 7 ? this.regsCur[reg] : (this.regsCur[reg] | 0x10000));
|
||||
return (reg === 7 ? this.regsGen[reg] : (this.regsGen[reg] | 0x10000));
|
||||
case 2: // Mode 2: (R)+
|
||||
stepSize = 2;
|
||||
virtualAddress = this.regsCur[reg];
|
||||
virtualAddress = this.regsGen[reg];
|
||||
if (reg !== 7) {
|
||||
virtualAddress |= 0x10000;
|
||||
if (reg < 6 && (accessMode & PDP11.BYTE_MODE)) {
|
||||
|
|
@ -1070,7 +1098,7 @@ CPUStatePDP11.prototype.getVirtualByMode = function(addressMode, accessMode)
|
|||
break;
|
||||
case 3: // Mode 3: @(R)+
|
||||
stepSize = 2;
|
||||
virtualAddress = this.regsCur[reg];
|
||||
virtualAddress = this.regsGen[reg];
|
||||
if (reg !== 7) virtualAddress |= 0x10000;
|
||||
if ((virtualAddress = this.readWordByVirtual(virtualAddress)) < 0) {
|
||||
return virtualAddress;
|
||||
|
|
@ -1081,14 +1109,14 @@ CPUStatePDP11.prototype.getVirtualByMode = function(addressMode, accessMode)
|
|||
case 4: // Mode 4: -(R)
|
||||
stepSize = -2;
|
||||
if (reg < 6 && (accessMode & PDP11.BYTE_MODE)) stepSize = -1;
|
||||
virtualAddress = (this.regsCur[reg] + stepSize) & 0xffff;
|
||||
virtualAddress = (this.regsGen[reg] + stepSize) & 0xffff;
|
||||
if (reg !== 7) {
|
||||
virtualAddress |= 0x10000;
|
||||
}
|
||||
break;
|
||||
case 5: // Mode 5: @-(R)
|
||||
stepSize = -2;
|
||||
virtualAddress = (this.regsCur[reg] - 2) & 0xffff;
|
||||
virtualAddress = (this.regsGen[reg] - 2) & 0xffff;
|
||||
if (reg !== 7) virtualAddress |= 0x10000;
|
||||
if ((virtualAddress = this.readWordByVirtual(virtualAddress)) < 0) {
|
||||
return virtualAddress;
|
||||
|
|
@ -1096,28 +1124,28 @@ CPUStatePDP11.prototype.getVirtualByMode = function(addressMode, accessMode)
|
|||
virtualAddress |= 0x10000;
|
||||
break;
|
||||
case 6: // Mode 6: d(R)
|
||||
if ((virtualAddress = this.readWordByVirtual(this.regsCur[7])) < 0) {
|
||||
if ((virtualAddress = this.readWordByVirtual(this.regsGen[7])) < 0) {
|
||||
return virtualAddress;
|
||||
}
|
||||
this.regsCur[7] = (this.regsCur[7] + 2) & 0xffff;
|
||||
this.regsGen[7] = (this.regsGen[7] + 2) & 0xffff;
|
||||
if (reg < 7) {
|
||||
//LOG_ADDRESS(virtualAddress);
|
||||
virtualAddress = (virtualAddress + this.regsCur[reg]) & 0xffff;
|
||||
virtualAddress = (virtualAddress + this.regsGen[reg]) & 0xffff;
|
||||
} else {
|
||||
virtualAddress = (virtualAddress + this.regsCur[reg]) & 0xffff;
|
||||
virtualAddress = (virtualAddress + this.regsGen[reg]) & 0xffff;
|
||||
//LOG_ADDRESS(virtualAddress);
|
||||
}
|
||||
return virtualAddress | 0x10000;
|
||||
case 7: // Mode 7: @d(R)
|
||||
if ((virtualAddress = this.readWordByVirtual(this.regsCur[7])) < 0) {
|
||||
if ((virtualAddress = this.readWordByVirtual(this.regsGen[7])) < 0) {
|
||||
return virtualAddress;
|
||||
}
|
||||
this.regsCur[7] = (this.regsCur[7] + 2) & 0xffff;
|
||||
this.regsGen[7] = (this.regsGen[7] + 2) & 0xffff;
|
||||
if (reg < 7) {
|
||||
//LOG_ADDRESS(virtualAddress);
|
||||
virtualAddress = (virtualAddress + this.regsCur[reg]) & 0xffff;
|
||||
virtualAddress = (virtualAddress + this.regsGen[reg]) & 0xffff;
|
||||
} else {
|
||||
virtualAddress = (virtualAddress + this.regsCur[reg]) & 0xffff;
|
||||
virtualAddress = (virtualAddress + this.regsGen[reg]) & 0xffff;
|
||||
//LOG_ADDRESS(virtualAddress);
|
||||
}
|
||||
if ((virtualAddress = this.readWordByVirtual(virtualAddress | 0x10000)) < 0) {
|
||||
|
|
@ -1125,15 +1153,15 @@ CPUStatePDP11.prototype.getVirtualByMode = function(addressMode, accessMode)
|
|||
}
|
||||
return virtualAddress | 0x10000; // @x
|
||||
}
|
||||
this.regsCur[reg] = (this.regsCur[reg] + stepSize) & 0xffff;
|
||||
this.regsGen[reg] = (this.regsGen[reg] + stepSize) & 0xffff;
|
||||
if (!(this.MMR0 & 0xe000)) {
|
||||
this.MMR1 = (this.MMR1 << 8) | ((stepSize << 3) & 0xf8) | reg;
|
||||
}
|
||||
if (reg === 6 && (!this.mmuMode) && (accessMode & PDP11.WRITE_MODE) && stepSize <= 0 &&
|
||||
(this.regsCur[6] <= this.stackLimit || this.regsCur[6] >= 0xfffe)) {
|
||||
if (this.regsCur[6] <= this.stackLimit - 32) {
|
||||
(this.regsGen[6] <= this.stackLimit || this.regsGen[6] >= 0xfffe)) {
|
||||
if (this.regsGen[6] <= this.stackLimit - 32) {
|
||||
this.CPU_Error |= 4; // Red stack
|
||||
this.regsCur[6] = 4;
|
||||
this.regsGen[6] = 4;
|
||||
return this.trap(4, 38);
|
||||
}
|
||||
this.CPU_Error |= 8; // Yellow
|
||||
|
|
@ -1174,7 +1202,7 @@ CPUStatePDP11.prototype.readWordByMode = function(addressMode)
|
|||
{
|
||||
var result;
|
||||
if (!(addressMode & 0x38)) {
|
||||
result = this.regsCur[addressMode & 7];
|
||||
result = this.regsGen[addressMode & 7];
|
||||
//LOG_SOURCE(result);
|
||||
} else {
|
||||
if ((result = this.getAddrByMode(addressMode, PDP11.READ_MODE)) >= 0) {
|
||||
|
|
@ -1197,7 +1225,7 @@ CPUStatePDP11.prototype.readByteByMode = function(addressMode)
|
|||
{
|
||||
var result;
|
||||
if (!(addressMode & 0x38)) {
|
||||
result = this.regsCur[addressMode & 7] & 0xff;
|
||||
result = this.regsGen[addressMode & 7] & 0xff;
|
||||
//LOG_SOURCE(result);
|
||||
} else {
|
||||
if ((result = this.getAddrByMode(addressMode, PDP11.READ_MODE | PDP11.BYTE_MODE)) >= 0) {
|
||||
|
|
@ -1340,25 +1368,25 @@ CPUStatePDP11.prototype.stepCPU = function(nMinCycles)
|
|||
}
|
||||
}
|
||||
}
|
||||
//if (this.regsCur[7] === this.debugPC) {
|
||||
//if (this.regsGen[7] === this.debugPC) {
|
||||
//LOG_PRINT();
|
||||
//
|
||||
//}
|
||||
// Initialize this.memory before getting an instruction
|
||||
if (!(this.MMR0 & 0xe000)) {
|
||||
this.MMR1 = 0;
|
||||
this.MMR2 = this.regsCur[7];
|
||||
this.MMR2 = this.regsGen[7];
|
||||
}
|
||||
// If needed T-bit trap at the end of this instruction
|
||||
this.trapMask = this.PSW & 0x10;
|
||||
if ((instruction = this.readWordByVirtual(this.regsCur[7])) >= 0) {
|
||||
this.regsCur[7] = (this.regsCur[7] + 2) & 0xffff;
|
||||
if ((instruction = this.readWordByVirtual(this.regsGen[7])) >= 0) {
|
||||
this.regsGen[7] = (this.regsGen[7] + 2) & 0xffff;
|
||||
switch (instruction & 0xF000) /*0170000*/ { // Double operand instructions xxSSDD
|
||||
case 0x1000: /*0010000*/ // MOV 01SSDD
|
||||
//LOG_INSTRUCTION(instruction, 2, "MOV");
|
||||
if ((src = this.readWordByMode(instruction >> 6)) >= 0) {
|
||||
if (!(instruction & 0x38)) {
|
||||
this.regsCur[instruction & 7] = src;
|
||||
this.regsGen[instruction & 7] = src;
|
||||
this.flagN = this.flagZ = src;
|
||||
this.flagV = 0;
|
||||
} else {
|
||||
|
|
@ -1394,7 +1422,7 @@ CPUStatePDP11.prototype.stepCPU = function(nMinCycles)
|
|||
//LOG_INSTRUCTION(instruction, 2, "BIC");
|
||||
if ((src = this.readWordByMode(instruction >> 6)) >= 0) {
|
||||
if (!(instruction & 0x38)) {
|
||||
result = this.regsCur[instruction & 7] &= ~src;
|
||||
result = this.regsGen[instruction & 7] &= ~src;
|
||||
this.flagN = this.flagZ = result;
|
||||
this.flagV = 0;
|
||||
} else {
|
||||
|
|
@ -1412,7 +1440,7 @@ CPUStatePDP11.prototype.stepCPU = function(nMinCycles)
|
|||
//LOG_INSTRUCTION(instruction, 2, "BIS");
|
||||
if ((src = this.readWordByMode(instruction >> 6)) >= 0) {
|
||||
if (!(instruction & 0x38)) {
|
||||
result = this.regsCur[instruction & 7] |= src;
|
||||
result = this.regsGen[instruction & 7] |= src;
|
||||
this.flagN = this.flagZ = result;
|
||||
this.flagV = 0;
|
||||
} else {
|
||||
|
|
@ -1431,8 +1459,8 @@ CPUStatePDP11.prototype.stepCPU = function(nMinCycles)
|
|||
if ((src = this.readWordByMode(instruction >> 6)) >= 0) {
|
||||
if (!(instruction & 0x38)) {
|
||||
reg = instruction & 7;
|
||||
dst = this.regsCur[reg];
|
||||
this.regsCur[reg] = (result = src + dst) & 0xffff;
|
||||
dst = this.regsGen[reg];
|
||||
this.regsGen[reg] = (result = src + dst) & 0xffff;
|
||||
this.flagN = this.flagZ = this.flagC = result;
|
||||
this.flagV = (src ^ result) & (dst ^ result);
|
||||
} else {
|
||||
|
|
@ -1451,7 +1479,7 @@ CPUStatePDP11.prototype.stepCPU = function(nMinCycles)
|
|||
if ((src = this.readByteByMode(instruction >> 6)) >= 0) {
|
||||
if (!(instruction & 0x38)) {
|
||||
if (src & 0x80) /*0200*/ src |= 0xff00; // movb sign extends register to word size
|
||||
this.regsCur[instruction & 7] = src;
|
||||
this.regsGen[instruction & 7] = src;
|
||||
this.flagN = this.flagZ = src;
|
||||
this.flagV = 0;
|
||||
} else {
|
||||
|
|
@ -1512,8 +1540,8 @@ CPUStatePDP11.prototype.stepCPU = function(nMinCycles)
|
|||
if ((src = this.readWordByMode(instruction >> 6)) >= 0) {
|
||||
if (!(instruction & 0x38)) {
|
||||
reg = instruction & 7;
|
||||
dst = this.regsCur[reg];
|
||||
this.regsCur[reg] = (result = dst - src) & 0xffff;
|
||||
dst = this.regsGen[reg];
|
||||
this.regsGen[reg] = (result = dst - src) & 0xffff;
|
||||
this.flagN = this.flagZ = this.flagC = result;
|
||||
this.flagV = (src ^ dst) & (dst ^ result);
|
||||
} else {
|
||||
|
|
@ -1533,9 +1561,9 @@ CPUStatePDP11.prototype.stepCPU = function(nMinCycles)
|
|||
//LOG_INSTRUCTION(instruction, 3, "JSR");
|
||||
if ((virtualAddress = this.getVirtualByMode(instruction, 0)) >= 0) {
|
||||
reg = (instruction >> 6) & 7;
|
||||
if (this.pushWord(this.regsCur[reg]) >= 0) {
|
||||
this.regsCur[reg] = this.regsCur[7];
|
||||
this.regsCur[7] = virtualAddress & 0xffff;
|
||||
if (this.pushWord(this.regsGen[reg]) >= 0) {
|
||||
this.regsGen[reg] = this.regsGen[7];
|
||||
this.regsGen[7] = virtualAddress & 0xffff;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
|
@ -1544,11 +1572,11 @@ CPUStatePDP11.prototype.stepCPU = function(nMinCycles)
|
|||
if ((src = this.readWordByMode(instruction)) >= 0) {
|
||||
reg = (instruction >> 6) & 7;
|
||||
if (src & 0x8000) src |= ~0xffff;
|
||||
dst = this.regsCur[reg];
|
||||
dst = this.regsGen[reg];
|
||||
if (dst & 0x8000) dst |= ~0xffff;
|
||||
result = ~~(src * dst);
|
||||
this.regsCur[reg] = (result >> 16) & 0xffff;
|
||||
this.regsCur[reg | 1] = result & 0xffff;
|
||||
this.regsGen[reg] = (result >> 16) & 0xffff;
|
||||
this.regsGen[reg | 1] = result & 0xffff;
|
||||
this.flagN = result >> 16;
|
||||
this.flagZ = this.flagN | result;
|
||||
this.flagC = this.flagV = 0;
|
||||
|
|
@ -1565,21 +1593,21 @@ CPUStatePDP11.prototype.stepCPU = function(nMinCycles)
|
|||
this.flagC = 0x10000; // divide by zero
|
||||
} else {
|
||||
reg = (instruction >> 6) & 7;
|
||||
dst = (this.regsCur[reg] << 16) | this.regsCur[reg | 1];
|
||||
dst = (this.regsGen[reg] << 16) | this.regsGen[reg | 1];
|
||||
this.flagC = this.flagV = 0;
|
||||
if (src & 0x8000) src |= ~0xffff;
|
||||
result = ~~(dst / src);
|
||||
if (result >= -32768 && result <= 32767) {
|
||||
this.regsCur[reg] = result & 0xffff;
|
||||
this.regsCur[reg | 1] = (dst - (result * src)) & 0xffff;
|
||||
this.regsGen[reg] = result & 0xffff;
|
||||
this.regsGen[reg | 1] = (dst - (result * src)) & 0xffff;
|
||||
this.flagZ = (result >> 16) | result;
|
||||
this.flagN = result >> 16;
|
||||
} else {
|
||||
this.flagV = 0x8000; // overflow - following are indeterminate
|
||||
this.flagZ = (result >> 15) | result; // dodgy
|
||||
this.flagN = dst >> 16; // just as dodgy
|
||||
if (src === -1 && this.regsCur[reg] ===
|
||||
0xfffe) this.regsCur[reg] = this.regsCur[reg | 1] = 1; // etc
|
||||
if (src === -1 && this.regsGen[reg] ===
|
||||
0xfffe) this.regsGen[reg] = this.regsGen[reg | 1] = 1; // etc
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1588,7 +1616,7 @@ CPUStatePDP11.prototype.stepCPU = function(nMinCycles)
|
|||
//LOG_INSTRUCTION(instruction, 3, "ASH");
|
||||
if ((src = this.readWordByMode(instruction)) >= 0) {
|
||||
reg = (instruction >> 6) & 7;
|
||||
result = this.regsCur[reg];
|
||||
result = this.regsGen[reg];
|
||||
if (result & 0x8000) result |= 0xffff0000;
|
||||
this.flagC = this.flagV = 0;
|
||||
src &= 0x3F; /*077*/
|
||||
|
|
@ -1610,7 +1638,7 @@ CPUStatePDP11.prototype.stepCPU = function(nMinCycles)
|
|||
}
|
||||
}
|
||||
}
|
||||
this.regsCur[reg] = result & 0xffff;
|
||||
this.regsGen[reg] = result & 0xffff;
|
||||
this.flagN = this.flagZ = result;
|
||||
}
|
||||
break;
|
||||
|
|
@ -1618,7 +1646,7 @@ CPUStatePDP11.prototype.stepCPU = function(nMinCycles)
|
|||
//LOG_INSTRUCTION(instruction, 3, "ASHC");
|
||||
if ((src = this.readWordByMode(instruction)) >= 0) {
|
||||
reg = (instruction >> 6) & 7;
|
||||
dst = (this.regsCur[reg] << 16) | this.regsCur[reg | 1];
|
||||
dst = (this.regsGen[reg] << 16) | this.regsGen[reg | 1];
|
||||
this.flagC = this.flagV = 0;
|
||||
src &= 0x3F; /*077*/
|
||||
if (src & 0x20) /*040*/ {
|
||||
|
|
@ -1643,8 +1671,8 @@ CPUStatePDP11.prototype.stepCPU = function(nMinCycles)
|
|||
result = dst;
|
||||
}
|
||||
}
|
||||
this.regsCur[reg] = (result >> 16) & 0xffff;
|
||||
this.regsCur[reg | 1] = result & 0xffff;
|
||||
this.regsGen[reg] = (result >> 16) & 0xffff;
|
||||
this.regsGen[reg | 1] = result & 0xffff;
|
||||
this.flagN = result >> 16;
|
||||
this.flagZ = result >> 16 | result;
|
||||
}
|
||||
|
|
@ -1652,12 +1680,12 @@ CPUStatePDP11.prototype.stepCPU = function(nMinCycles)
|
|||
case 0x7800: /*0074000*/ // XOR 074RSS
|
||||
//LOG_INSTRUCTION(instruction, 3, "XOR");
|
||||
if (!(instruction & 0x38)) {
|
||||
dst = this.regsCur[instruction & 7] ^= this.regsCur[(instruction >> 6) & 7];
|
||||
dst = this.regsGen[instruction & 7] ^= this.regsGen[(instruction >> 6) & 7];
|
||||
this.flagN = this.flagZ = dst;
|
||||
this.flagV = 0;
|
||||
} else {
|
||||
if ((dst = this.readWordByAddr(dstAddr = this.getAddrByMode(instruction, PDP11.MODIFY_WORD))) >= 0) {
|
||||
dst ^= this.regsCur[(instruction >> 6) & 7];
|
||||
dst ^= this.regsGen[(instruction >> 6) & 7];
|
||||
if (this.writeWordByAddr(dstAddr, dst) >= 0) {
|
||||
this.flagN = this.flagZ = dst;
|
||||
this.flagV = 0;
|
||||
|
|
@ -1668,78 +1696,78 @@ CPUStatePDP11.prototype.stepCPU = function(nMinCycles)
|
|||
case 0x7E00: /*0077000*/ // SOB 077Rnn
|
||||
//LOG_INSTRUCTION(instruction, 5, "SOB");
|
||||
reg = (instruction >> 6) & 7;
|
||||
if ((this.regsCur[reg] = ((this.regsCur[reg] - 1) & 0xffff))) {
|
||||
this.regsCur[7] = (this.regsCur[7] - ((instruction & 0x3F) /*077*/ << 1)) & 0xffff;
|
||||
if ((this.regsGen[reg] = ((this.regsGen[reg] - 1) & 0xffff))) {
|
||||
this.regsGen[7] = (this.regsGen[7] - ((instruction & 0x3F) /*077*/ << 1)) & 0xffff;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
switch (instruction & 0xFF00) /*0177400*/ { // Program control instructions & traps
|
||||
case 0x100: /*0000400*/ // BR
|
||||
//LOG_INSTRUCTION(instruction, 4, "BR");
|
||||
this.regsCur[7] = this.branch(this.regsCur[7], instruction);
|
||||
this.regsGen[7] = this.branch(this.regsGen[7], instruction);
|
||||
break;
|
||||
case 0x200: /*0001000*/ // BNE
|
||||
//LOG_INSTRUCTION(instruction, 4, "BNE");
|
||||
if (this.flagZ & 0xffff) this.regsCur[7] = this.branch(this.regsCur[7], instruction);
|
||||
if (this.flagZ & 0xffff) this.regsGen[7] = this.branch(this.regsGen[7], instruction);
|
||||
break;
|
||||
case 0x300: /*0001400*/ // BEQ
|
||||
//LOG_INSTRUCTION(instruction, 4, "BEQ");
|
||||
if (!(this.flagZ & 0xffff)) this.regsCur[7] = this.branch(this.regsCur[7], instruction);
|
||||
if (!(this.flagZ & 0xffff)) this.regsGen[7] = this.branch(this.regsGen[7], instruction);
|
||||
break;
|
||||
case 0x400: /*0002000*/ // BGE
|
||||
//LOG_INSTRUCTION(instruction, 4, "BGE");
|
||||
if ((this.flagN & 0x8000) ===
|
||||
(this.flagV & 0x8000)) this.regsCur[7] = this.branch(this.regsCur[7], instruction);
|
||||
(this.flagV & 0x8000)) this.regsGen[7] = this.branch(this.regsGen[7], instruction);
|
||||
break;
|
||||
case 0x500: /*0002400*/ // BLT
|
||||
//LOG_INSTRUCTION(instruction, 4, "BLT");
|
||||
if ((this.flagN & 0x8000) !==
|
||||
(this.flagV & 0x8000)) this.regsCur[7] = this.branch(this.regsCur[7], instruction);
|
||||
(this.flagV & 0x8000)) this.regsGen[7] = this.branch(this.regsGen[7], instruction);
|
||||
break;
|
||||
case 0x600: /*0003000*/ // BGT
|
||||
//LOG_INSTRUCTION(instruction, 4, "BGT");
|
||||
if ((this.flagZ & 0xffff) && ((this.flagN & 0x8000) ===
|
||||
(this.flagV & 0x8000))) this.regsCur[7] = this.branch(this.regsCur[7], instruction);
|
||||
(this.flagV & 0x8000))) this.regsGen[7] = this.branch(this.regsGen[7], instruction);
|
||||
break;
|
||||
case 0x700: /*0003400*/ // BLE
|
||||
//LOG_INSTRUCTION(instruction, 4, "BLE");
|
||||
if (!(this.flagZ & 0xffff) || ((this.flagN & 0x8000) !==
|
||||
(this.flagV & 0x8000))) this.regsCur[7] = this.branch(this.regsCur[7], instruction);
|
||||
(this.flagV & 0x8000))) this.regsGen[7] = this.branch(this.regsGen[7], instruction);
|
||||
break;
|
||||
case 0x8000: /*0100000*/ // BPL
|
||||
//LOG_INSTRUCTION(instruction, 4, "BPL");
|
||||
if (!(this.flagN & 0x8000)) this.regsCur[7] = this.branch(this.regsCur[7], instruction);
|
||||
if (!(this.flagN & 0x8000)) this.regsGen[7] = this.branch(this.regsGen[7], instruction);
|
||||
break;
|
||||
case 0x8200: /*0101000*/ // BHI
|
||||
//LOG_INSTRUCTION(instruction, 4, "BHI");
|
||||
if (!(this.flagC & 0x10000) &&
|
||||
(this.flagZ & 0xffff)) this.regsCur[7] = this.branch(this.regsCur[7], instruction);
|
||||
(this.flagZ & 0xffff)) this.regsGen[7] = this.branch(this.regsGen[7], instruction);
|
||||
break;
|
||||
case 0x8100: /*0100400*/ // BMI
|
||||
//LOG_INSTRUCTION(instruction, 4, "BMI");
|
||||
if ((this.flagN & 0x8000)) this.regsCur[7] = this.branch(this.regsCur[7], instruction);
|
||||
if ((this.flagN & 0x8000)) this.regsGen[7] = this.branch(this.regsGen[7], instruction);
|
||||
break;
|
||||
case 0x8300: /*0101400*/ // BLOS
|
||||
//LOG_INSTRUCTION(instruction, 4, "BLOS");
|
||||
if ((this.flagC & 0x10000) ||
|
||||
!(this.flagZ & 0xffff)) this.regsCur[7] = this.branch(this.regsCur[7], instruction);
|
||||
!(this.flagZ & 0xffff)) this.regsGen[7] = this.branch(this.regsGen[7], instruction);
|
||||
break;
|
||||
case 0x8400: /*0102000*/ // BVC
|
||||
//LOG_INSTRUCTION(instruction, 4, "BVC");
|
||||
if (!(this.flagV & 0x8000)) this.regsCur[7] = this.branch(this.regsCur[7], instruction);
|
||||
if (!(this.flagV & 0x8000)) this.regsGen[7] = this.branch(this.regsGen[7], instruction);
|
||||
break;
|
||||
case 0x8500: /*0102400*/ // BVS
|
||||
//LOG_INSTRUCTION(instruction, 4, "BVS");
|
||||
if ((this.flagV & 0x8000)) this.regsCur[7] = this.branch(this.regsCur[7], instruction);
|
||||
if ((this.flagV & 0x8000)) this.regsGen[7] = this.branch(this.regsGen[7], instruction);
|
||||
break;
|
||||
case 0x8600: /*0103000*/ // BCC
|
||||
//LOG_INSTRUCTION(instruction, 4, "BCC");
|
||||
if (!(this.flagC &
|
||||
0x10000)) this.regsCur[7] = this.branch(this.regsCur[7], instruction);
|
||||
0x10000)) this.regsGen[7] = this.branch(this.regsGen[7], instruction);
|
||||
break;
|
||||
case 0x8700: /*0103400*/ // BCS
|
||||
//LOG_INSTRUCTION(instruction, 4, "BCS");
|
||||
if (this.flagC & 0x10000) this.regsCur[7] = this.branch(this.regsCur[7], instruction);
|
||||
if (this.flagC & 0x10000) this.regsGen[7] = this.branch(this.regsGen[7], instruction);
|
||||
break;
|
||||
case 0x8800: /*0104000*/ // EMT 104000 -> 104377
|
||||
//LOG_INSTRUCTION(instruction, 7, "EMT");
|
||||
|
|
@ -1754,15 +1782,15 @@ CPUStatePDP11.prototype.stepCPU = function(nMinCycles)
|
|||
case 0x40: /*0000100*/ // JMP 0001DD
|
||||
//LOG_INSTRUCTION(instruction, 1, "JMP");
|
||||
if ((virtualAddress = this.getVirtualByMode(instruction, 0)) >= 0) {
|
||||
this.regsCur[7] = virtualAddress & 0xffff;
|
||||
this.regsGen[7] = virtualAddress & 0xffff;
|
||||
}
|
||||
break;
|
||||
case 0xC0: /*0000300*/ // SWAB 0003DD
|
||||
//LOG_INSTRUCTION(instruction, 1, "SWAB");
|
||||
if (!(instruction & 0x38)) {
|
||||
reg = instruction & 7;
|
||||
dst = this.regsCur[reg];
|
||||
this.regsCur[reg] = ((dst << 8) | (dst >> 8)) & 0xffff;
|
||||
dst = this.regsGen[reg];
|
||||
this.regsGen[reg] = ((dst << 8) | (dst >> 8)) & 0xffff;
|
||||
this.flagN = this.flagZ = dst & 0xff00;
|
||||
this.flagV = this.flagC = 0;
|
||||
} else {
|
||||
|
|
@ -1779,7 +1807,7 @@ CPUStatePDP11.prototype.stepCPU = function(nMinCycles)
|
|||
case 0xA00: /*0005000*/ // CLR 0050DD
|
||||
//LOG_INSTRUCTION(instruction, 1, "CLR");
|
||||
if (!(instruction & 0x38)) {
|
||||
this.regsCur[instruction & 7] = 0;
|
||||
this.regsGen[instruction & 7] = 0;
|
||||
this.flagN = this.flagC = this.flagV = this.flagZ = 0;
|
||||
} else {
|
||||
if ((dstAddr = this.getAddrByMode(instruction, PDP11.WRITE_MODE)) >= 0) { // write word
|
||||
|
|
@ -1805,9 +1833,9 @@ CPUStatePDP11.prototype.stepCPU = function(nMinCycles)
|
|||
//LOG_INSTRUCTION(instruction, 1, "INC");
|
||||
if (!(instruction & 0x38)) {
|
||||
reg = instruction & 7;
|
||||
dst = this.regsCur[reg];
|
||||
dst = this.regsGen[reg];
|
||||
result = dst + 1;
|
||||
this.regsCur[reg] = result & 0xffff;
|
||||
this.regsGen[reg] = result & 0xffff;
|
||||
this.flagN = this.flagZ = result;
|
||||
this.flagV = result & (result ^ dst);
|
||||
} else {
|
||||
|
|
@ -1825,9 +1853,9 @@ CPUStatePDP11.prototype.stepCPU = function(nMinCycles)
|
|||
//LOG_INSTRUCTION(instruction, 1, "DEC");
|
||||
if (!(instruction & 0x38)) {
|
||||
reg = instruction & 7;
|
||||
dst = this.regsCur[reg];
|
||||
dst = this.regsGen[reg];
|
||||
result = dst - 1;
|
||||
this.regsCur[reg] = result & 0xffff;
|
||||
this.regsGen[reg] = result & 0xffff;
|
||||
this.flagN = this.flagZ = result;
|
||||
this.flagV = (result ^ dst) & dst;
|
||||
} else {
|
||||
|
|
@ -1885,9 +1913,9 @@ CPUStatePDP11.prototype.stepCPU = function(nMinCycles)
|
|||
//LOG_INSTRUCTION(instruction, 1, "ROR");
|
||||
if (!(instruction & 0x38)) {
|
||||
reg = instruction & 7;
|
||||
dst = this.regsCur[reg];
|
||||
dst = this.regsGen[reg];
|
||||
result = ((this.flagC & 0x10000) | dst) >> 1;
|
||||
this.regsCur[reg] = result & 0xffff;
|
||||
this.regsGen[reg] = result & 0xffff;
|
||||
this.flagC = (dst << 16);
|
||||
this.flagN = this.flagZ = result;
|
||||
this.flagV = result ^ (this.flagC >> 1);
|
||||
|
|
@ -1907,9 +1935,9 @@ CPUStatePDP11.prototype.stepCPU = function(nMinCycles)
|
|||
//LOG_INSTRUCTION(instruction, 1, "ROL");
|
||||
if (!(instruction & 0x38)) {
|
||||
reg = instruction & 7;
|
||||
dst = this.regsCur[reg];
|
||||
dst = this.regsGen[reg];
|
||||
result = (dst << 1) | ((this.flagC >> 16) & 1);
|
||||
this.regsCur[reg] = result & 0xffff;
|
||||
this.regsGen[reg] = result & 0xffff;
|
||||
this.flagC = this.flagN = this.flagZ = result;
|
||||
this.flagV = result ^ dst;
|
||||
} else {
|
||||
|
|
@ -1927,9 +1955,9 @@ CPUStatePDP11.prototype.stepCPU = function(nMinCycles)
|
|||
//LOG_INSTRUCTION(instruction, 1, "ASR");
|
||||
if (!(instruction & 0x38)) {
|
||||
reg = instruction & 7;
|
||||
dst = this.regsCur[reg];
|
||||
dst = this.regsGen[reg];
|
||||
result = (dst & 0x8000) | (dst >> 1);
|
||||
this.regsCur[reg] = result & 0xffff;
|
||||
this.regsGen[reg] = result & 0xffff;
|
||||
this.flagC = dst << 16;
|
||||
this.flagN = this.flagZ = result;
|
||||
this.flagV = this.flagN ^ (this.flagC >> 1);
|
||||
|
|
@ -1949,9 +1977,9 @@ CPUStatePDP11.prototype.stepCPU = function(nMinCycles)
|
|||
//LOG_INSTRUCTION(instruction, 1, "ASL");
|
||||
if (!(instruction & 0x38)) {
|
||||
reg = instruction & 7;
|
||||
dst = this.regsCur[reg];
|
||||
dst = this.regsGen[reg];
|
||||
result = dst << 1;
|
||||
this.regsCur[reg] = result & 0xffff;
|
||||
this.regsGen[reg] = result & 0xffff;
|
||||
this.flagC = this.flagN = this.flagZ = result;
|
||||
this.flagV = result ^ dst;
|
||||
} else {
|
||||
|
|
@ -1967,11 +1995,11 @@ CPUStatePDP11.prototype.stepCPU = function(nMinCycles)
|
|||
break;
|
||||
case 0xD00: /*0006400*/ // MARK 0064nn
|
||||
//LOG_INSTRUCTION(instruction, 8, "MARK");
|
||||
virtualAddress = (this.regsCur[7] + ((instruction & 0x3F) /*077*/ << 1)) & 0xffff;
|
||||
virtualAddress = (this.regsGen[7] + ((instruction & 0x3F) /*077*/ << 1)) & 0xffff;
|
||||
if ((src = this.readWordByVirtual(virtualAddress | 0x10000)) >= 0) {
|
||||
this.regsCur[7] = this.regsCur[5];
|
||||
this.regsCur[5] = src;
|
||||
this.regsCur[6] = (virtualAddress + 2) & 0xffff;
|
||||
this.regsGen[7] = this.regsGen[5];
|
||||
this.regsGen[5] = src;
|
||||
this.regsGen[6] = (virtualAddress + 2) & 0xffff;
|
||||
}
|
||||
break;
|
||||
case 0xD40: /*0006500*/ // MFPI 0065SS
|
||||
|
|
@ -1979,9 +2007,9 @@ CPUStatePDP11.prototype.stepCPU = function(nMinCycles)
|
|||
if (!(instruction & 0x38)) {
|
||||
reg = instruction & 7;
|
||||
if (6 !== reg || ((this.PSW >> 2) & 0x3000) === (this.PSW & 0x3000)) {
|
||||
src = this.regsCur[reg];
|
||||
src = this.regsGen[reg];
|
||||
} else {
|
||||
src = this.regsStack[(this.PSW >> 12) & 3];
|
||||
src = this.regsAltStack[(this.PSW >> 12) & 3];
|
||||
}
|
||||
if (this.pushWord(src) >= 0) {
|
||||
this.flagN = this.flagZ = src;
|
||||
|
|
@ -2008,9 +2036,9 @@ CPUStatePDP11.prototype.stepCPU = function(nMinCycles)
|
|||
if (!(instruction & 0x38)) {
|
||||
reg = instruction & 7;
|
||||
if (6 !== reg || ((this.PSW >> 2) & 0x3000) === (this.PSW & 0x3000)) {
|
||||
this.regsCur[reg] = dst;
|
||||
this.regsGen[reg] = dst;
|
||||
} else {
|
||||
this.regsStack[(this.PSW >> 12) & 3] = dst;
|
||||
this.regsAltStack[(this.PSW >> 12) & 3] = dst;
|
||||
}
|
||||
this.flagN = this.flagZ = dst;
|
||||
this.flagV = 0;
|
||||
|
|
@ -2042,7 +2070,7 @@ CPUStatePDP11.prototype.stepCPU = function(nMinCycles)
|
|||
case 0x8A00: /*0105000*/ // CLRB 1050DD
|
||||
//LOG_INSTRUCTION(instruction, 1, "CLRB");
|
||||
if (!(instruction & 0x38)) {
|
||||
this.regsCur[instruction & 7] &= 0xff00;
|
||||
this.regsGen[instruction & 7] &= 0xff00;
|
||||
this.flagN = this.flagC = this.flagV = this.flagZ = 0;
|
||||
} else {
|
||||
if ((dstAddr = this.getAddrByMode(instruction, PDP11.WRITE_MODE | PDP11.BYTE_MODE)) >= 0) { // write byte
|
||||
|
|
@ -2183,9 +2211,9 @@ CPUStatePDP11.prototype.stepCPU = function(nMinCycles)
|
|||
if (!(instruction & 0x38)) {
|
||||
reg = instruction & 7;
|
||||
if (6 !== reg || ((this.PSW >> 2) & 0x3000) === (this.PSW & 0x3000)) {
|
||||
src = this.regsCur[reg];
|
||||
src = this.regsGen[reg];
|
||||
} else {
|
||||
src = this.regsStack[(this.PSW >> 12) & 3];
|
||||
src = this.regsAltStack[(this.PSW >> 12) & 3];
|
||||
}
|
||||
if (this.pushWord(src) >= 0) {
|
||||
this.flagN = this.flagZ = src;
|
||||
|
|
@ -2211,9 +2239,9 @@ CPUStatePDP11.prototype.stepCPU = function(nMinCycles)
|
|||
if (!(instruction & 0x38)) {
|
||||
reg = instruction & 7;
|
||||
if (6 !== reg || ((this.PSW >> 2) & 0x3000) === (this.PSW & 0x3000)) {
|
||||
this.regsCur[reg] = dst;
|
||||
this.regsGen[reg] = dst;
|
||||
} else {
|
||||
this.regsStack[(this.PSW >> 12) & 3] = dst;
|
||||
this.regsAltStack[(this.PSW >> 12) & 3] = dst;
|
||||
}
|
||||
this.flagN = this.flagZ = dst;
|
||||
this.flagV = 0;
|
||||
|
|
@ -2244,7 +2272,7 @@ CPUStatePDP11.prototype.stepCPU = function(nMinCycles)
|
|||
// }
|
||||
// } else {
|
||||
// if (src & 0200) src |= 0xff00;
|
||||
// this.regsCur[instruction & 7] = src;
|
||||
// this.regsGen[instruction & 7] = src;
|
||||
// this.flagN = this.flagZ = src << 8;
|
||||
// this.flagV = 0;
|
||||
// } // Temporary PDP 11/34A
|
||||
|
|
@ -2255,8 +2283,8 @@ CPUStatePDP11.prototype.stepCPU = function(nMinCycles)
|
|||
//LOG_INSTRUCTION(instruction, 6, "RTS");
|
||||
if ((src = this.popWord()) >= 0) {
|
||||
reg = instruction & 7;
|
||||
this.regsCur[7] = this.regsCur[reg];
|
||||
this.regsCur[reg] = src;
|
||||
this.regsGen[7] = this.regsGen[reg];
|
||||
this.regsGen[reg] = src;
|
||||
}
|
||||
break;
|
||||
case 0x98: /*0000230*/ // SPL 00023N
|
||||
|
|
@ -2293,7 +2321,7 @@ CPUStatePDP11.prototype.stepCPU = function(nMinCycles)
|
|||
this.runState = 3; // halt
|
||||
this.endBurst();
|
||||
//LOG_PRINT();
|
||||
console.log("HALT at " + this.regsCur[7].toString(8));
|
||||
console.log("HALT at " + this.regsGen[7].toString(8));
|
||||
}
|
||||
break;
|
||||
case 0x1: /*0000001*/ // WAIT 000001
|
||||
|
|
@ -2323,23 +2351,23 @@ CPUStatePDP11.prototype.stepCPU = function(nMinCycles)
|
|||
if (!(this.PSW & 0xc000)) {
|
||||
this.resetRegs();
|
||||
this.bus.reset_iopage();
|
||||
// display.data = this.regsCur[0]; // TODO: Review
|
||||
// display.data = this.regsGen[0]; // TODO: Review
|
||||
}
|
||||
break;
|
||||
case 0x2: /*0000002*/ // RTI 000002
|
||||
case 0x6: /*0000006*/ // RTT 000006
|
||||
//LOG_INSTRUCTION(instruction, 0, "RTT");
|
||||
dstAddr = this.regsCur[6];
|
||||
dstAddr = this.regsGen[6];
|
||||
if ((virtualAddress = this.readWordByVirtual(dstAddr | 0x10000)) >= 0) {
|
||||
dstAddr = (dstAddr + 2) & 0xffff;
|
||||
if ((savePSW = this.readWordByVirtual(dstAddr | 0x10000)) >= 0) {
|
||||
this.regsCur[6] = (dstAddr + 2) & 0xffff;
|
||||
this.regsGen[6] = (dstAddr + 2) & 0xffff;
|
||||
savePSW &= 0xf8ff;
|
||||
if (this.PSW & 0xc000) { // user / super restrictions
|
||||
// keep SPL and allow lower only for modes and register set
|
||||
savePSW = (savePSW & 0xf81f) | (this.PSW & 0xf8e0);
|
||||
}
|
||||
this.regsCur[7] = virtualAddress;
|
||||
this.regsGen[7] = virtualAddress;
|
||||
this.writePSW(savePSW);
|
||||
this.trapMask &= ~0x10; // turn off Trace trap
|
||||
if (instruction === 2) this.trapMask |= this.PSW & 0x10; // RTI enables immediate trace
|
||||
|
|
@ -2348,7 +2376,7 @@ CPUStatePDP11.prototype.stepCPU = function(nMinCycles)
|
|||
break;
|
||||
//case 0000007: // MFPT 000007
|
||||
// //LOG_INSTRUCTION(instruction, 0, "MFPT");
|
||||
// this.regsCur[0] = 1;
|
||||
// this.regsGen[0] = 1;
|
||||
// break; // Exists on pdp 11/44 & KB11-EM
|
||||
default: // We don't know this instruction
|
||||
//LOG_INSTRUCTION(instruction, 11, "-unknown-");
|
||||
|
|
|
|||
|
|
@ -229,7 +229,8 @@ if (DEBUGGER) {
|
|||
ROLB: 72, ROR: 73, RORB: 74, RTI: 75, RTS: 76, SBC: 77, SBCB: 78, SCC: 79,
|
||||
SEC: 80, SECN: 81, SECV: 82, SECVN: 83, SECVZ: 84, SECZ: 85, SECZN: 86, SEN: 87,
|
||||
SEV: 88, SEVN: 89, SEVZ: 90, SEVZN: 91, SEZ: 92, SEZN: 93, SUB: 94, SWAB: 95,
|
||||
SXT: 96, TST: 97, TSTB: 98, WAIT: 99
|
||||
SXT: 96, TST: 97, TSTB: 98, WAIT: 99, MUL: 100, DIV: 101, ASH: 102, ASHC: 103,
|
||||
XOR: 104, SOB: 105, EMT: 106, TRAP: 107, SPL: 108, IOT: 109, RTT: 110, MFPT: 111
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
@ -248,11 +249,12 @@ if (DEBUGGER) {
|
|||
"ROLB", "ROR", "RORB", "RTI", "RTS", "SBC", "SBCB", "SCC",
|
||||
"SEC", "SECN", "SECV", "SECVN", "SECVZ", "SECZ", "SECZN", "SEN",
|
||||
"SEV", "SEVN", "SEVZ", "SEVZN", "SEZ", "SEZN", "SUB", "SWAB",
|
||||
"SXT", "TST", "TSTB", "WAIT"
|
||||
"SXT", "TST", "TSTB", "WAIT", "MUL", "DIV", "ASH", "ASHC",
|
||||
"XOR", "SOB", "EMT", "TRAP", "SPL", "IOT", "RTT", "MFPT"
|
||||
];
|
||||
|
||||
/*
|
||||
* Register numbers 0-7 are reserved for cpu.regsCur, 8-15 are reserved for cpu.regsAlt, and 16-19 for cpu.regsStack.
|
||||
* Register numbers 0-7 are reserved for cpu.regsGen, 8-15 are reserved for cpu.regsAlt, and 16-19 for cpu.regsStack.
|
||||
*/
|
||||
DebuggerPDP11.REG_SP = 6; // aka R6
|
||||
DebuggerPDP11.REG_PC = 7; // aka R7
|
||||
|
|
@ -268,7 +270,7 @@ if (DEBUGGER) {
|
|||
DebuggerPDP11.MODE_INDEXD = 0x7; // INDEX DEFERRED (register + next word is address of address of operand)
|
||||
|
||||
/*
|
||||
* Operand descriptor masks
|
||||
* Operand descriptor masks; anything that's not covered by TYPE_SRC or TYPE_DST must be a TYPE_OTHER value.
|
||||
*/
|
||||
DebuggerPDP11.TYPE_DSTREG = 0x0007;
|
||||
DebuggerPDP11.TYPE_DSTMOD = 0x0038;
|
||||
|
|
@ -277,36 +279,51 @@ if (DEBUGGER) {
|
|||
DebuggerPDP11.TYPE_SRCMOD = 0x0E00;
|
||||
DebuggerPDP11.TYPE_SRC = (DebuggerPDP11.TYPE_SRCMOD | DebuggerPDP11.TYPE_SRCREG);
|
||||
DebuggerPDP11.TYPE_BRANCH = 0x1000;
|
||||
DebuggerPDP11.TYPE_DSTOFF = 0x2000;
|
||||
DebuggerPDP11.TYPE_DSTNUM3 = 0x3000; // DST 3-bit number (ie, just the DSTREG field)
|
||||
DebuggerPDP11.TYPE_DSTNUM6 = 0x6000; // DST 6-bit number (ie, both the DSTREG and DSTMOD fields)
|
||||
DebuggerPDP11.TYPE_OTHER = 0xF000;
|
||||
|
||||
/*
|
||||
* The opMasks table contains opcode masks, and each mask refers to table of possible values,
|
||||
* and each value refers to an array that contains:
|
||||
* The opMasks table contains opcode masks, and each mask refers to table of possible values, and each
|
||||
* value refers to an array that contains:
|
||||
*
|
||||
* [0]: {number} of the opcode name (see OP.*)
|
||||
* [1]: {number} containing the first operand descriptor bit(s), if any
|
||||
* [2]: {number} containing the second operand descriptor bit(s), if any
|
||||
*
|
||||
* These sub-elements are all optional. If [0] is not present, the opcode is undefined; if [1] is not
|
||||
* present (or contains zero), the opcode has no (or only implied) operands; if [2] is not present, the
|
||||
* opcode has only a single operand. And so on.
|
||||
* Note that, by convention, opcodes that require two operands list the SRC operand first and DST operand
|
||||
* second (ie, the OPPOSITE of the Intel convention).
|
||||
*
|
||||
* Also note that, for some of the newer PDP-11 opcodes (eg, MUL, DIV, ASH, ASCH), the location of the
|
||||
* opcode's SRC and DST bits are reversed. This is why, for example, you'll see the MUL instruction defined
|
||||
* below as having TYPE_DST for the first operand and TYPE_SRCREG for the second operand. This does NOT mean
|
||||
* that the opcode's destination operand is being listed first, but rather that the bits describing the source
|
||||
* operand are in the opcode's TYPE_DST field.
|
||||
*/
|
||||
DebuggerPDP11.opMasks = {
|
||||
0xF000: {
|
||||
0x1000: [DebuggerPDP11.OPS.MOV, DebuggerPDP11.TYPE_SRC, DebuggerPDP11.TYPE_DST],
|
||||
0x2000: [DebuggerPDP11.OPS.CMP, DebuggerPDP11.TYPE_SRC, DebuggerPDP11.TYPE_DST],
|
||||
0x3000: [DebuggerPDP11.OPS.BIT, DebuggerPDP11.TYPE_SRC, DebuggerPDP11.TYPE_DST],
|
||||
0x4000: [DebuggerPDP11.OPS.BIC, DebuggerPDP11.TYPE_SRC, DebuggerPDP11.TYPE_DST],
|
||||
0x5000: [DebuggerPDP11.OPS.BIS, DebuggerPDP11.TYPE_SRC, DebuggerPDP11.TYPE_DST],
|
||||
0x6000: [DebuggerPDP11.OPS.ADD, DebuggerPDP11.TYPE_SRC, DebuggerPDP11.TYPE_DST],
|
||||
0x9000: [DebuggerPDP11.OPS.MOVB, DebuggerPDP11.TYPE_SRC, DebuggerPDP11.TYPE_DST],
|
||||
0xA000: [DebuggerPDP11.OPS.CMPB, DebuggerPDP11.TYPE_SRC, DebuggerPDP11.TYPE_DST],
|
||||
0xB000: [DebuggerPDP11.OPS.BITB, DebuggerPDP11.TYPE_SRC, DebuggerPDP11.TYPE_DST],
|
||||
0xC000: [DebuggerPDP11.OPS.BICB, DebuggerPDP11.TYPE_SRC, DebuggerPDP11.TYPE_DST],
|
||||
0xD000: [DebuggerPDP11.OPS.BISB, DebuggerPDP11.TYPE_SRC, DebuggerPDP11.TYPE_DST],
|
||||
0xE000: [DebuggerPDP11.OPS.SUB, DebuggerPDP11.TYPE_SRC, DebuggerPDP11.TYPE_DST]
|
||||
0x1000: [DebuggerPDP11.OPS.MOV, DebuggerPDP11.TYPE_SRC, DebuggerPDP11.TYPE_DST], // 01SSDD
|
||||
0x2000: [DebuggerPDP11.OPS.CMP, DebuggerPDP11.TYPE_SRC, DebuggerPDP11.TYPE_DST], // 02SSDD
|
||||
0x3000: [DebuggerPDP11.OPS.BIT, DebuggerPDP11.TYPE_SRC, DebuggerPDP11.TYPE_DST], // 03SSDD
|
||||
0x4000: [DebuggerPDP11.OPS.BIC, DebuggerPDP11.TYPE_SRC, DebuggerPDP11.TYPE_DST], // 04SSDD
|
||||
0x5000: [DebuggerPDP11.OPS.BIS, DebuggerPDP11.TYPE_SRC, DebuggerPDP11.TYPE_DST], // 05SSDD
|
||||
0x6000: [DebuggerPDP11.OPS.ADD, DebuggerPDP11.TYPE_SRC, DebuggerPDP11.TYPE_DST], // 06SSDD
|
||||
0x9000: [DebuggerPDP11.OPS.MOVB, DebuggerPDP11.TYPE_SRC, DebuggerPDP11.TYPE_DST], // 11SSDD
|
||||
0xA000: [DebuggerPDP11.OPS.CMPB, DebuggerPDP11.TYPE_SRC, DebuggerPDP11.TYPE_DST], // 12SSDD
|
||||
0xB000: [DebuggerPDP11.OPS.BITB, DebuggerPDP11.TYPE_SRC, DebuggerPDP11.TYPE_DST], // 13SSDD
|
||||
0xC000: [DebuggerPDP11.OPS.BICB, DebuggerPDP11.TYPE_SRC, DebuggerPDP11.TYPE_DST], // 14SSDD
|
||||
0xD000: [DebuggerPDP11.OPS.BISB, DebuggerPDP11.TYPE_SRC, DebuggerPDP11.TYPE_DST], // 15SSDD
|
||||
0xE000: [DebuggerPDP11.OPS.SUB, DebuggerPDP11.TYPE_SRC, DebuggerPDP11.TYPE_DST] // 16SSDD
|
||||
},
|
||||
0xFE00: {
|
||||
0x0800: [DebuggerPDP11.OPS.JSR, DebuggerPDP11.TYPE_SRCREG, DebuggerPDP11.TYPE_DST]
|
||||
0x0800: [DebuggerPDP11.OPS.JSR, DebuggerPDP11.TYPE_SRCREG, DebuggerPDP11.TYPE_DST], // 004RDD
|
||||
0x7000: [DebuggerPDP11.OPS.MUL, DebuggerPDP11.TYPE_DST, DebuggerPDP11.TYPE_SRCREG], // 070RSS
|
||||
0x7200: [DebuggerPDP11.OPS.DIV, DebuggerPDP11.TYPE_DST, DebuggerPDP11.TYPE_SRCREG], // 071RSS
|
||||
0x7400: [DebuggerPDP11.OPS.ASH, DebuggerPDP11.TYPE_DST, DebuggerPDP11.TYPE_SRCREG], // 072RSS
|
||||
0x7600: [DebuggerPDP11.OPS.ASHC, DebuggerPDP11.TYPE_DST, DebuggerPDP11.TYPE_SRCREG], // 073RSS
|
||||
0x7800: [DebuggerPDP11.OPS.XOR, DebuggerPDP11.TYPE_SRCREG, DebuggerPDP11.TYPE_DST], // 074RSS
|
||||
0x7E00: [DebuggerPDP11.OPS.SOB, DebuggerPDP11.TYPE_SRCREG, DebuggerPDP11.TYPE_DSTOFF] // 077Rnn
|
||||
},
|
||||
0xFF00: {
|
||||
0x0100: [DebuggerPDP11.OPS.BR, DebuggerPDP11.TYPE_BRANCH],
|
||||
|
|
@ -323,53 +340,59 @@ if (DEBUGGER) {
|
|||
0x8400: [DebuggerPDP11.OPS.BVC, DebuggerPDP11.TYPE_BRANCH],
|
||||
0x8500: [DebuggerPDP11.OPS.BVS, DebuggerPDP11.TYPE_BRANCH],
|
||||
0x8600: [DebuggerPDP11.OPS.BCC, DebuggerPDP11.TYPE_BRANCH],
|
||||
0x8700: [DebuggerPDP11.OPS.BCS, DebuggerPDP11.TYPE_BRANCH]
|
||||
0x8700: [DebuggerPDP11.OPS.BCS, DebuggerPDP11.TYPE_BRANCH],
|
||||
0x8800: [DebuggerPDP11.OPS.EMT], // 104000..104377
|
||||
0x8900: [DebuggerPDP11.OPS.TRAP] // 104400..104777
|
||||
},
|
||||
0xFFC0: {
|
||||
0x0010: [DebuggerPDP11.OPS.JMP, DebuggerPDP11.TYPE_DST],
|
||||
0x00C0: [DebuggerPDP11.OPS.SWAB, DebuggerPDP11.TYPE_DST],
|
||||
0x0480: [DebuggerPDP11.OPS.INC, DebuggerPDP11.TYPE_DST],
|
||||
0x0A00: [DebuggerPDP11.OPS.CLR, DebuggerPDP11.TYPE_DST],
|
||||
0x0A40: [DebuggerPDP11.OPS.COM, DebuggerPDP11.TYPE_DST],
|
||||
0x0AC0: [DebuggerPDP11.OPS.DEC, DebuggerPDP11.TYPE_DST],
|
||||
0x0B00: [DebuggerPDP11.OPS.NEG, DebuggerPDP11.TYPE_DST],
|
||||
0x0B40: [DebuggerPDP11.OPS.ADC, DebuggerPDP11.TYPE_DST],
|
||||
0x0B80: [DebuggerPDP11.OPS.SBC, DebuggerPDP11.TYPE_DST],
|
||||
0x0BC0: [DebuggerPDP11.OPS.TST, DebuggerPDP11.TYPE_DST],
|
||||
0x0C00: [DebuggerPDP11.OPS.ROR, DebuggerPDP11.TYPE_DST],
|
||||
0x0C40: [DebuggerPDP11.OPS.ROL, DebuggerPDP11.TYPE_DST],
|
||||
0x0C80: [DebuggerPDP11.OPS.ASR, DebuggerPDP11.TYPE_DST],
|
||||
0x0CC0: [DebuggerPDP11.OPS.ASL, DebuggerPDP11.TYPE_DST],
|
||||
0x0D00: [DebuggerPDP11.OPS.MARK, DebuggerPDP11.TYPE_DST],
|
||||
0x0D40: [DebuggerPDP11.OPS.MFPI, DebuggerPDP11.TYPE_DST],
|
||||
0x0D80: [DebuggerPDP11.OPS.MTPI, DebuggerPDP11.TYPE_DST],
|
||||
0x0DC0: [DebuggerPDP11.OPS.SXT, DebuggerPDP11.TYPE_DST],
|
||||
0x8480: [DebuggerPDP11.OPS.INCB, DebuggerPDP11.TYPE_DST],
|
||||
0x8A00: [DebuggerPDP11.OPS.CLRB, DebuggerPDP11.TYPE_DST],
|
||||
0x8A40: [DebuggerPDP11.OPS.COMB, DebuggerPDP11.TYPE_DST],
|
||||
0x8AC0: [DebuggerPDP11.OPS.DECB, DebuggerPDP11.TYPE_DST],
|
||||
0x8B00: [DebuggerPDP11.OPS.NEGB, DebuggerPDP11.TYPE_DST],
|
||||
0x8B40: [DebuggerPDP11.OPS.ADCB, DebuggerPDP11.TYPE_DST],
|
||||
0x8B80: [DebuggerPDP11.OPS.SBCB, DebuggerPDP11.TYPE_DST],
|
||||
0x8BC0: [DebuggerPDP11.OPS.TSTB, DebuggerPDP11.TYPE_DST],
|
||||
0x8C00: [DebuggerPDP11.OPS.RORB, DebuggerPDP11.TYPE_DST],
|
||||
0x8C40: [DebuggerPDP11.OPS.ROLB, DebuggerPDP11.TYPE_DST],
|
||||
0x8C80: [DebuggerPDP11.OPS.ASRB, DebuggerPDP11.TYPE_DST],
|
||||
0x8CC0: [DebuggerPDP11.OPS.ASLB, DebuggerPDP11.TYPE_DST],
|
||||
0x8D00: [DebuggerPDP11.OPS.MTPS, DebuggerPDP11.TYPE_DST], // only on LSI-11
|
||||
0x8D40: [DebuggerPDP11.OPS.MFPD, DebuggerPDP11.TYPE_DST], // same as MFPI if no separate instruction/data spaces
|
||||
0x8D80: [DebuggerPDP11.OPS.MTPD, DebuggerPDP11.TYPE_DST], // same as MTPI if no separate instruction/data spaces
|
||||
0x8DC0: [DebuggerPDP11.OPS.MFPS, DebuggerPDP11.TYPE_DST] // only on LSI-11
|
||||
0x0040: [DebuggerPDP11.OPS.JMP, DebuggerPDP11.TYPE_DST], // 0001DD
|
||||
0x00C0: [DebuggerPDP11.OPS.SWAB, DebuggerPDP11.TYPE_DST], // 0003DD
|
||||
0x0A00: [DebuggerPDP11.OPS.CLR, DebuggerPDP11.TYPE_DST], // 0050DD
|
||||
0x0A40: [DebuggerPDP11.OPS.COM, DebuggerPDP11.TYPE_DST], // 0051DD
|
||||
0x0A80: [DebuggerPDP11.OPS.INC, DebuggerPDP11.TYPE_DST], // 0052DD
|
||||
0x0AC0: [DebuggerPDP11.OPS.DEC, DebuggerPDP11.TYPE_DST], // 0053DD
|
||||
0x0B00: [DebuggerPDP11.OPS.NEG, DebuggerPDP11.TYPE_DST], // 0054DD
|
||||
0x0B40: [DebuggerPDP11.OPS.ADC, DebuggerPDP11.TYPE_DST], // 0055DD
|
||||
0x0B80: [DebuggerPDP11.OPS.SBC, DebuggerPDP11.TYPE_DST], // 0056DD
|
||||
0x0BC0: [DebuggerPDP11.OPS.TST, DebuggerPDP11.TYPE_DST], // 0057DD
|
||||
0x0C00: [DebuggerPDP11.OPS.ROR, DebuggerPDP11.TYPE_DST], // 0060DD
|
||||
0x0C40: [DebuggerPDP11.OPS.ROL, DebuggerPDP11.TYPE_DST], // 0061DD
|
||||
0x0C80: [DebuggerPDP11.OPS.ASR, DebuggerPDP11.TYPE_DST], // 0062DD
|
||||
0x0CC0: [DebuggerPDP11.OPS.ASL, DebuggerPDP11.TYPE_DST], // 0063DD
|
||||
0x0D00: [DebuggerPDP11.OPS.MARK, DebuggerPDP11.TYPE_DSTNUM6], // 0064nn
|
||||
0x0D40: [DebuggerPDP11.OPS.MFPI, DebuggerPDP11.TYPE_DST], // 0065SS
|
||||
0x0D80: [DebuggerPDP11.OPS.MTPI, DebuggerPDP11.TYPE_DST], // 0066DD
|
||||
0x0DC0: [DebuggerPDP11.OPS.SXT, DebuggerPDP11.TYPE_DST], // 0067DD
|
||||
0x8A00: [DebuggerPDP11.OPS.CLRB, DebuggerPDP11.TYPE_DST], // 1050DD
|
||||
0x8A40: [DebuggerPDP11.OPS.COMB, DebuggerPDP11.TYPE_DST], // 1051DD
|
||||
0x8A80: [DebuggerPDP11.OPS.INCB, DebuggerPDP11.TYPE_DST], // 1052DD
|
||||
0x8AC0: [DebuggerPDP11.OPS.DECB, DebuggerPDP11.TYPE_DST], // 1053DD
|
||||
0x8B00: [DebuggerPDP11.OPS.NEGB, DebuggerPDP11.TYPE_DST], // 1054DD
|
||||
0x8B40: [DebuggerPDP11.OPS.ADCB, DebuggerPDP11.TYPE_DST], // 1055DD
|
||||
0x8B80: [DebuggerPDP11.OPS.SBCB, DebuggerPDP11.TYPE_DST], // 1056DD
|
||||
0x8BC0: [DebuggerPDP11.OPS.TSTB, DebuggerPDP11.TYPE_DST], // 1057DD
|
||||
0x8C00: [DebuggerPDP11.OPS.RORB, DebuggerPDP11.TYPE_DST], // 1060DD
|
||||
0x8C40: [DebuggerPDP11.OPS.ROLB, DebuggerPDP11.TYPE_DST], // 1061DD
|
||||
0x8C80: [DebuggerPDP11.OPS.ASRB, DebuggerPDP11.TYPE_DST], // 1062DD
|
||||
0x8CC0: [DebuggerPDP11.OPS.ASLB, DebuggerPDP11.TYPE_DST], // 1063DD
|
||||
0x8D00: [DebuggerPDP11.OPS.MTPS, DebuggerPDP11.TYPE_DST], // 1064SS (only on LSI-11)
|
||||
0x8D40: [DebuggerPDP11.OPS.MFPD, DebuggerPDP11.TYPE_DST], // 1065DD (same as MFPI if no separate instruction/data spaces)
|
||||
0x8D80: [DebuggerPDP11.OPS.MTPD, DebuggerPDP11.TYPE_DST], // 1066DD (same as MTPI if no separate instruction/data spaces)
|
||||
0x8DC0: [DebuggerPDP11.OPS.MFPS, DebuggerPDP11.TYPE_DST] // 1067SS (only on LSI-11)
|
||||
},
|
||||
0xFFF8: {
|
||||
0x0080: [DebuggerPDP11.OPS.RTS, DebuggerPDP11.TYPE_SRCREG]
|
||||
0x0080: [DebuggerPDP11.OPS.RTS, DebuggerPDP11.TYPE_DSTREG], // 00020R
|
||||
0x0098: [DebuggerPDP11.OPS.SPL, DebuggerPDP11.TYPE_DSTNUM3] // 00023N
|
||||
},
|
||||
0xFFFF: {
|
||||
0x0000: [DebuggerPDP11.OPS.HALT],
|
||||
0x0001: [DebuggerPDP11.OPS.WAIT],
|
||||
0x0002: [DebuggerPDP11.OPS.RTI],
|
||||
0x0004: [DebuggerPDP11.OPS.BPT],
|
||||
0x0005: [DebuggerPDP11.OPS.RESET],
|
||||
0x0000: [DebuggerPDP11.OPS.HALT], // 000000
|
||||
0x0001: [DebuggerPDP11.OPS.WAIT], // 000001
|
||||
0x0002: [DebuggerPDP11.OPS.RTI], // 000002
|
||||
0x0003: [DebuggerPDP11.OPS.BPT], // 000003
|
||||
0x0004: [DebuggerPDP11.OPS.IOT], // 000004
|
||||
0x0005: [DebuggerPDP11.OPS.RESET], // 000005
|
||||
0x0006: [DebuggerPDP11.OPS.RTT], // 000006
|
||||
0x0007: [DebuggerPDP11.OPS.MFPT], // 000007
|
||||
0x00A0: [DebuggerPDP11.OPS.NOP],
|
||||
0x00A1: [DebuggerPDP11.OPS.CLC],
|
||||
0x00A2: [DebuggerPDP11.OPS.CLV],
|
||||
|
|
@ -385,7 +408,7 @@ if (DEBUGGER) {
|
|||
0x00AC: [DebuggerPDP11.OPS.CLZN],
|
||||
0x00AD: [DebuggerPDP11.OPS.CLCZN],
|
||||
0x00AE: [DebuggerPDP11.OPS.CLVZN],
|
||||
0x00AF: [DebuggerPDP11.OPS.CCC], // aka CLCVZN
|
||||
0x00AF: [DebuggerPDP11.OPS.CCC], // aka CLCVZN
|
||||
0x00B0: [DebuggerPDP11.OPS.NOP],
|
||||
0x00B1: [DebuggerPDP11.OPS.SEC],
|
||||
0x00B2: [DebuggerPDP11.OPS.SEV],
|
||||
|
|
@ -401,7 +424,7 @@ if (DEBUGGER) {
|
|||
0x00BC: [DebuggerPDP11.OPS.SEZN],
|
||||
0x00BD: [DebuggerPDP11.OPS.SECZN],
|
||||
0x00BE: [DebuggerPDP11.OPS.SEVZN],
|
||||
0x00BF: [DebuggerPDP11.OPS.SCC] // aka SECVZN
|
||||
0x00BF: [DebuggerPDP11.OPS.SCC] // aka SECVZN
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -1942,16 +1965,30 @@ if (DEBUGGER) {
|
|||
*/
|
||||
DebuggerPDP11.prototype.getOperand = function(opCode, type, dbgAddr)
|
||||
{
|
||||
var sOperand = "";
|
||||
var sOperand = "", disp, addr;
|
||||
/*
|
||||
* Take care of TYPE_BRANCH opcodes first; then all we'll have to worry about
|
||||
* Take care of TYPE_OTHER opcodes first; then all we'll have to worry about
|
||||
* next are TYPE_SRC or TYPE_DST opcodes.
|
||||
*/
|
||||
if (type & DebuggerPDP11.TYPE_BRANCH) {
|
||||
var disp = ((opCode & 0xff) << 24) >> 24;
|
||||
var addr = (dbgAddr.addr + disp) & 0xffff;
|
||||
var typeOther = type & DebuggerPDP11.TYPE_OTHER;
|
||||
if (typeOther == DebuggerPDP11.TYPE_BRANCH) {
|
||||
disp = ((opCode & 0xff) << 24) >> 24;
|
||||
addr = (dbgAddr.addr + disp) & 0xffff;
|
||||
sOperand = str.toHexWord(addr);
|
||||
}
|
||||
else if (typeOther == DebuggerPDP11.TYPE_DSTOFF) {
|
||||
disp = (opCode & 0x3f) << 1;
|
||||
addr = (dbgAddr.addr - disp) & 0xffff;
|
||||
sOperand = str.toHexWord(addr);
|
||||
}
|
||||
else if (typeOther == DebuggerPDP11.TYPE_DSTNUM3) {
|
||||
disp = (opCode & 0x7);
|
||||
sOperand = str.toHexByte(disp);
|
||||
}
|
||||
else if (typeOther == DebuggerPDP11.TYPE_DSTNUM6) {
|
||||
disp = (opCode & 0x3f);
|
||||
sOperand = str.toHexByte(disp);
|
||||
}
|
||||
else {
|
||||
/*
|
||||
* Isolate all TYPE_SRC or TYPE_DST bits from opcode in the mode variable.
|
||||
|
|
@ -2056,11 +2093,14 @@ if (DEBUGGER) {
|
|||
var b;
|
||||
switch (sFlag) {
|
||||
case 'N':
|
||||
b = this.cpu.getSF();
|
||||
b = this.cpu.getNF();
|
||||
break;
|
||||
case 'Z':
|
||||
b = this.cpu.getZF();
|
||||
break;
|
||||
case 'V':
|
||||
b = this.cpu.getVF();
|
||||
break;
|
||||
case 'C':
|
||||
b = this.cpu.getCF();
|
||||
break;
|
||||
|
|
@ -2085,13 +2125,13 @@ if (DEBUGGER) {
|
|||
|
||||
if (iReg < 8) {
|
||||
sReg = (iReg < 6? ("R" + iReg) : (iReg == 6? "SP" : "PC"));
|
||||
sReg += '=' + str.toHex(cpu.regsCur[iReg], 4);
|
||||
sReg += '=' + str.toHex(cpu.regsGen[iReg], 4);
|
||||
}
|
||||
else if (iReg < 13) {
|
||||
sReg = "A" + (iReg - 8) + '=' + str.toHex(cpu.regsAlt[iReg - 8], 4);
|
||||
}
|
||||
else if (iReg >= 16 && iReg < 20) {
|
||||
sReg = "S" + (iReg - 16) + '=' + str.toHex(cpu.regsStack[iReg - 16], 4);
|
||||
sReg = "S" + (iReg - 16) + '=' + str.toHex(cpu.regsAltStack[iReg - 16], 4);
|
||||
}
|
||||
else if (iReg == DebuggerPDP11.REG_PSW) {
|
||||
sReg = "PS=" + str.toHex(cpu.getPSW(), 4);
|
||||
|
|
@ -3070,14 +3110,17 @@ if (DEBUGGER) {
|
|||
cpu.setPC(w);
|
||||
this.dbgAddrNextCode = this.newAddr(cpu.getPC());
|
||||
break;
|
||||
case "CF":
|
||||
if (w) cpu.setCF(); else cpu.clearCF();
|
||||
case "NF":
|
||||
if (w) cpu.setNF(); else cpu.clearNF();
|
||||
break;
|
||||
case "ZF":
|
||||
if (w) cpu.setZF(); else cpu.clearZF();
|
||||
break;
|
||||
case "SF":
|
||||
if (w) cpu.setSF(); else cpu.clearSF();
|
||||
case "VF":
|
||||
if (w) cpu.setVF(); else cpu.clearVF();
|
||||
break;
|
||||
case "CF":
|
||||
if (w) cpu.setCF(); else cpu.clearCF();
|
||||
break;
|
||||
default:
|
||||
this.println("unknown register: " + sReg);
|
||||
|
|
@ -3215,7 +3258,7 @@ if (DEBUGGER) {
|
|||
if (n > 2) {
|
||||
dbgAddr.addr = addr;
|
||||
var s = this.getInstruction(dbgAddr);
|
||||
if (s.indexOf("CALL") >= 0) {
|
||||
if (s.indexOf("JSR") >= 0) {
|
||||
/*
|
||||
* Verify that the length of this CALL (or INT), when added to the address of the CALL (or INT),
|
||||
* matches the original return address. We do this by getting the string index of the opcode bytes,
|
||||
|
|
|
|||
|
|
@ -122,21 +122,38 @@ var PDP11 = {
|
|||
* automatic inlining will no longer occur.
|
||||
*/
|
||||
ADDR_INVALID: -1,
|
||||
|
||||
/*
|
||||
* Processor Modes
|
||||
*/
|
||||
MODE: {
|
||||
KERNEL: 0x0,
|
||||
SUPER: 0x1,
|
||||
UNUSED: 0x2,
|
||||
USER: 0x3,
|
||||
MASK: 0x3
|
||||
},
|
||||
/*
|
||||
* Processor Status flag definitions (stored in regPSW)
|
||||
*/
|
||||
PSW: {
|
||||
CF: 0x0001, // bit 0: Carry Flag
|
||||
OF: 0x0002, // bit 1: Overflow Flag
|
||||
CF_SHIFT: 0,
|
||||
VF: 0x0002, // bit 1: Overflow Flag (aka OF on Intel processors)
|
||||
VF_SHIFT: 1,
|
||||
ZF: 0x0004, // bit 2: Zero Flag
|
||||
SF: 0x0008, // bit 3: Sign Flag
|
||||
ZF_SHIFT: 2,
|
||||
NF: 0x0008, // bit 3: Negative Flag (aka SF -- Sign Flag -- on Intel processors)
|
||||
NF_SHIFT: 3,
|
||||
TF: 0x0010, // bit 4: Trap Flag
|
||||
TF_SHIFT: 4,
|
||||
PRI: 0x00E0, // bits 5-7: Priority
|
||||
PRI_SHIFT: 5,
|
||||
UNUSED: 0x0700, // bits 8-10: unused
|
||||
REGSET: 0x0800, // bit 11: Register Set
|
||||
PMODE: 0x3000, // bits 12-13: Previous Mode
|
||||
CMODE: 0xC000 // bits 14-15: Current Mode
|
||||
PMODE: 0x3000, // bits 12-13: Previous Mode (see PDP11.MODE)
|
||||
PMODE_SHIFT:12,
|
||||
CMODE: 0xC000, // bits 14-15: Current Mode (see PDP11.MODE)
|
||||
CMODE_SHIFT:14
|
||||
},
|
||||
/*
|
||||
* Interrupt-related flags (stored in intFlags)
|
||||
|
|
@ -150,7 +167,7 @@ var PDP11 = {
|
|||
* Opcode definitions
|
||||
*/
|
||||
OPCODE: {
|
||||
// to be continued....
|
||||
// TODO
|
||||
},
|
||||
|
||||
IOBASE_VIRT: 0x00E000, /*000160000*/
|
||||
|
|
@ -168,18 +185,18 @@ var PDP11 = {
|
|||
};
|
||||
|
||||
/*
|
||||
* PSW "arithmetic" flags are NOT stored in the PSW register; they are maintained across separate result registers,
|
||||
* hence the RESULT designation.
|
||||
* PSW arithmetic flags are NOT stored directly into the PSW register; they are maintained across separate
|
||||
* flag registers.
|
||||
*/
|
||||
PDP11.PSW.RESULT = (PDP11.PSW.CF | PDP11.PSW.ZF | PDP11.PSW.SF);
|
||||
PDP11.PSW.FLAGS = (PDP11.PSW.NF | PDP11.PSW.ZF | PDP11.PSW.VF | PDP11.PSW.CF);
|
||||
|
||||
if (NODE) {
|
||||
global.APPCLASS = APPCLASS;
|
||||
global.APPNAME = APPNAME;
|
||||
global.DEBUGGER = DEBUGGER;
|
||||
global.BYTEARRAYS = BYTEARRAYS;
|
||||
global.TYPEDARRAYS = TYPEDARRAYS;
|
||||
global.PDP11 = PDP11;
|
||||
global.APPCLASS = APPCLASS;
|
||||
global.APPNAME = APPNAME;
|
||||
global.DEBUGGER = DEBUGGER;
|
||||
global.BYTEARRAYS = BYTEARRAYS;
|
||||
global.TYPEDARRAYS = TYPEDARRAYS;
|
||||
global.PDP11 = PDP11;
|
||||
|
||||
module.exports = PDP11;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue