Fixed Debugger memory editing and register handling, tidied up some flag operations, and removed more now-unnecessary address checks in cpustate
This commit is contained in:
parent
c7dbfc02be
commit
44a2ec9f03
9 changed files with 576 additions and 519 deletions
|
|
@ -39,18 +39,19 @@ if (NODE) {
|
|||
|
||||
/*
|
||||
* Decoding starts at the bottom of this file, in op1170(). The basic decoding approach is to
|
||||
* dispatch on the top 4 bits of the opcode, and if further decoding is required, then dispatch on
|
||||
* the next 4 bits, and so on (although some of the intermediate levels dispatch only on 2 bits).
|
||||
* dispatch on the top 4 bits of the opcode, and if further decoding is required, the dispatched
|
||||
* function will dispatch on the next 4 bits, and so on (although some of the intermediate levels
|
||||
* dispatch only on 2 bits, which could also handled with a switch statement).
|
||||
*
|
||||
* Eventually, every opcode should end up either in an opXXX() function or opUndefined(). For
|
||||
* opcodes that perform a simple read and/or write operation, the entire functionality is handled
|
||||
* by the opXXX() function. For opcodes that perform a more extensive read/modify/write operation
|
||||
* opcodes that perform a simple read and/or write operation, the entire operation is handled by
|
||||
* the opXXX() function. For opcodes that perform a more extensive read/modify/write operation
|
||||
* (also known as an update operation), those opXXX() functions usually rely on a corresponding
|
||||
* fnXXX() helper function.
|
||||
*
|
||||
* For example, opADD() passes the helper function fnADD() to the appropriate update method. This
|
||||
* allows the update method to perform the entire read/modify/write operation, because the modification
|
||||
* is handled by the helper function.
|
||||
* is performed internally via the helper function.
|
||||
*/
|
||||
|
||||
/**
|
||||
|
|
@ -94,7 +95,7 @@ PDP11.fnADDB = function(src, dst)
|
|||
PDP11.fnASL = function(src, dst)
|
||||
{
|
||||
var result = dst << 1;
|
||||
this.updateLogFlags(result);
|
||||
this.updateShiftFlags(result);
|
||||
return result & 0xffff;
|
||||
};
|
||||
|
||||
|
|
@ -109,7 +110,7 @@ PDP11.fnASL = function(src, dst)
|
|||
PDP11.fnASLB = function(src, dst)
|
||||
{
|
||||
var result = dst << 1;
|
||||
this.updateLogFlags(result << 8);
|
||||
this.updateShiftFlags(result << 8);
|
||||
return result & 0xff;
|
||||
};
|
||||
|
||||
|
|
@ -124,7 +125,7 @@ PDP11.fnASLB = function(src, dst)
|
|||
PDP11.fnASR = function(src, dst)
|
||||
{
|
||||
var result = (dst & 0x8000) | (dst >> 1) | (dst << 16);
|
||||
this.updateLogFlags(result);
|
||||
this.updateShiftFlags(result);
|
||||
return result & 0xffff;
|
||||
};
|
||||
|
||||
|
|
@ -139,7 +140,7 @@ PDP11.fnASR = function(src, dst)
|
|||
PDP11.fnASRB = function(src, dst)
|
||||
{
|
||||
var result = (dst & 0x800) | (dst >> 1) | (dst << 8);
|
||||
this.updateLogFlags(result << 8);
|
||||
this.updateShiftFlags(result << 8);
|
||||
return result & 0xff;
|
||||
};
|
||||
|
||||
|
|
@ -214,7 +215,7 @@ PDP11.fnBISB = function(src, dst)
|
|||
PDP11.fnCOM = function(src, dst)
|
||||
{
|
||||
var result = ~dst | 0x10000;
|
||||
this.updateNZCFlags(result);
|
||||
this.updateAllFlags(result);
|
||||
return result & 0xffff;
|
||||
};
|
||||
|
||||
|
|
@ -229,7 +230,7 @@ PDP11.fnCOM = function(src, dst)
|
|||
PDP11.fnCOMB = function(src, dst)
|
||||
{
|
||||
var result = ~dst | 0x100;
|
||||
this.updateNZCFlags(result << 8);
|
||||
this.updateAllFlags(result << 8);
|
||||
return result & 0xff;
|
||||
};
|
||||
|
||||
|
|
@ -307,7 +308,7 @@ PDP11.fnNEG = function(src, dst)
|
|||
/*
|
||||
* If the sign bit of both dst and result are set, the original value must have been 0x8000, triggering overflow.
|
||||
*/
|
||||
this.updateNZCFlags(result, result & dst & 0x8000);
|
||||
this.updateAllFlags(result, result & dst & 0x8000);
|
||||
return result & 0xffff;
|
||||
};
|
||||
|
||||
|
|
@ -325,7 +326,7 @@ PDP11.fnNEGB = function(src, dst)
|
|||
/*
|
||||
* If the sign bit of both dst and result are set, the original value must have been 0x80, which triggers overflow.
|
||||
*/
|
||||
this.updateNZCFlags(result << 8, (result & dst & 0x80) << 8);
|
||||
this.updateAllFlags(result << 8, (result & dst & 0x80) << 8);
|
||||
return result & 0xff;
|
||||
};
|
||||
|
||||
|
|
@ -340,7 +341,7 @@ PDP11.fnNEGB = function(src, dst)
|
|||
PDP11.fnROL = function(src, dst)
|
||||
{
|
||||
var result = (dst << 1) | ((this.flagC >> 16) & 1);
|
||||
this.updateLogFlags(result);
|
||||
this.updateShiftFlags(result);
|
||||
return result & 0xffff;
|
||||
};
|
||||
|
||||
|
|
@ -355,7 +356,7 @@ PDP11.fnROL = function(src, dst)
|
|||
PDP11.fnROLB = function(src, dst)
|
||||
{
|
||||
var result = (dst << 1) | ((this.flagC >> 16) & 1);
|
||||
this.updateLogFlags(result << 8);
|
||||
this.updateShiftFlags(result << 8);
|
||||
return result & 0xff;
|
||||
};
|
||||
|
||||
|
|
@ -370,7 +371,7 @@ PDP11.fnROLB = function(src, dst)
|
|||
PDP11.fnROR = function(src, dst)
|
||||
{
|
||||
var result = (((this.flagC & 0x10000) | dst) >> 1) | (dst << 16);
|
||||
this.updateLogFlags(result);
|
||||
this.updateShiftFlags(result);
|
||||
return result & 0xffff;
|
||||
};
|
||||
|
||||
|
|
@ -385,7 +386,7 @@ PDP11.fnROR = function(src, dst)
|
|||
PDP11.fnRORB = function(src, dst)
|
||||
{
|
||||
var result = ((((this.flagC & 0x10000) >> 8) | dst) >> 1) | (dst << 8);
|
||||
this.updateLogFlags(result << 8);
|
||||
this.updateShiftFlags(result << 8);
|
||||
return result & 0xff;
|
||||
};
|
||||
|
||||
|
|
@ -867,7 +868,7 @@ PDP11.opBVS = function(opCode)
|
|||
*/
|
||||
PDP11.opCLR = function(opCode)
|
||||
{
|
||||
this.updateNZCFlags(this.writeWordByMode(opCode, 0));
|
||||
this.updateAllFlags(this.writeWordByMode(opCode, 0));
|
||||
this.nStepCycles -= 1;
|
||||
};
|
||||
|
||||
|
|
@ -879,7 +880,7 @@ PDP11.opCLR = function(opCode)
|
|||
*/
|
||||
PDP11.opCLRB = function(opCode)
|
||||
{
|
||||
this.updateNZCFlags(this.writeByteByMode(opCode, 0));
|
||||
this.updateAllFlags(this.writeByteByMode(opCode, 0));
|
||||
this.nStepCycles -= 1;
|
||||
};
|
||||
|
||||
|
|
@ -1040,6 +1041,9 @@ PDP11.opDECB = function(opCode)
|
|||
*/
|
||||
PDP11.opDIV = function(opCode)
|
||||
{
|
||||
/*
|
||||
* TODO: Review and determine if flag updates can be encapsulated in an updateDivFlags() function.
|
||||
*/
|
||||
var src = this.readWordByMode(opCode);
|
||||
if (!src) {
|
||||
this.flagN = 0; // NZVC
|
||||
|
|
@ -1159,7 +1163,7 @@ PDP11.opJSR = function(opCode)
|
|||
*/
|
||||
PDP11.opMARK = function(opCode)
|
||||
{
|
||||
var addr = (this.regsGen[7] + ((opCode & 0x3F) << 1)) & 0xffff;
|
||||
var addr = (this.regsGen[PDP11.REG.PC] + ((opCode & 0x3F) << 1)) & 0xffff;
|
||||
var src = this.readWordFromVirtual(addr | 0x10000);
|
||||
this.setPC(this.regsGen[5]);
|
||||
this.setSP(addr + 2);
|
||||
|
|
@ -1264,10 +1268,7 @@ PDP11.opMUL = function(opCode)
|
|||
var result = ~~(src * dst);
|
||||
this.regsGen[reg] = (result >> 16) & 0xffff;
|
||||
this.regsGen[reg | 1] = result & 0xffff;
|
||||
this.flagN = result >> 16;
|
||||
this.flagZ = this.flagN | result;
|
||||
this.flagV = 0;
|
||||
this.flagC = (result < -32768 || result > 32767)? 0x10000 : 0;
|
||||
this.updateMulFlags(result);
|
||||
this.nStepCycles -= 1;
|
||||
};
|
||||
|
||||
|
|
@ -1511,7 +1512,7 @@ PDP11.opSOB = function(opCode)
|
|||
{
|
||||
var reg = (opCode & PDP11.SRCMODE.REG) >> PDP11.SRCMODE.SHIFT;
|
||||
if ((this.regsGen[reg] = ((this.regsGen[reg] - 1) & 0xffff))) {
|
||||
this.setPC(this.regsGen[7] - ((opCode & 0x3F) << 1));
|
||||
this.setPC(this.regsGen[PDP11.REG.PC] - ((opCode & 0x3F) << 1));
|
||||
}
|
||||
this.nStepCycles -= 1;
|
||||
};
|
||||
|
|
@ -1578,7 +1579,7 @@ PDP11.opTST = function(opCode)
|
|||
{
|
||||
var result = this.readWordByMode(opCode);
|
||||
this.assert(!(result & ~0xffff)); // assert that C flag will be clear
|
||||
this.updateNZCFlags(result);
|
||||
this.updateAllFlags(result);
|
||||
this.nStepCycles -= 1;
|
||||
};
|
||||
|
||||
|
|
@ -1592,7 +1593,7 @@ PDP11.opTSTB = function(opCode)
|
|||
{
|
||||
var result = this.readByteByMode(opCode);
|
||||
this.assert(!(result & ~0xff)); // assert that C flag will be clear
|
||||
this.updateNZCFlags(result << 8);
|
||||
this.updateAllFlags(result << 8);
|
||||
this.nStepCycles -= 1;
|
||||
};
|
||||
|
||||
|
|
@ -1643,45 +1644,45 @@ PDP11.op0Xnn_1170 = function(opCode)
|
|||
};
|
||||
|
||||
/**
|
||||
* op0Ann_1170(opCode)
|
||||
* op0AXn_1170(opCode)
|
||||
*
|
||||
* @this {CPUStatePDP11}
|
||||
* @param {number} opCode
|
||||
*/
|
||||
PDP11.op0Ann_1170 = function(opCode)
|
||||
PDP11.op0AXn_1170 = function(opCode)
|
||||
{
|
||||
PDP11.aOps0AXn_1170[(opCode >> 6) & 0x3].call(this, opCode);
|
||||
};
|
||||
|
||||
/**
|
||||
* op0Bnn_1170(opCode)
|
||||
* op0BXn_1170(opCode)
|
||||
*
|
||||
* @this {CPUStatePDP11}
|
||||
* @param {number} opCode
|
||||
*/
|
||||
PDP11.op0Bnn_1170 = function(opCode)
|
||||
PDP11.op0BXn_1170 = function(opCode)
|
||||
{
|
||||
PDP11.aOps0BXn_1170[(opCode >> 6) & 0x3].call(this, opCode);
|
||||
};
|
||||
|
||||
/**
|
||||
* op0Cnn_1170(opCode)
|
||||
* op0CXn_1170(opCode)
|
||||
*
|
||||
* @this {CPUStatePDP11}
|
||||
* @param {number} opCode
|
||||
*/
|
||||
PDP11.op0Cnn_1170 = function(opCode)
|
||||
PDP11.op0CXn_1170 = function(opCode)
|
||||
{
|
||||
PDP11.aOps0CXn_1170[(opCode >> 6) & 0x3].call(this, opCode);
|
||||
};
|
||||
|
||||
/**
|
||||
* op0Dnn_1170(opCode)
|
||||
* op0DXn_1170(opCode)
|
||||
*
|
||||
* @this {CPUStatePDP11}
|
||||
* @param {number} opCode
|
||||
*/
|
||||
PDP11.op0Dnn_1170 = function(opCode)
|
||||
PDP11.op0DXn_1170 = function(opCode)
|
||||
{
|
||||
PDP11.aOps0DXn_1170[(opCode >> 6) & 0x3].call(this, opCode);
|
||||
};
|
||||
|
|
@ -1848,14 +1849,42 @@ PDP11.aOps0Xnn_1170 = [
|
|||
PDP11.opBLE, // 0x07nn
|
||||
PDP11.opJSR, // 0x08nn
|
||||
PDP11.opJSR, // 0x09nn
|
||||
PDP11.op0Ann_1170, // 0x0Ann
|
||||
PDP11.op0Bnn_1170, // 0x0Bnn
|
||||
PDP11.op0Cnn_1170, // 0x0Cnn
|
||||
PDP11.op0Dnn_1170, // 0x0Dnn
|
||||
PDP11.op0AXn_1170, // 0x0Ann
|
||||
PDP11.op0BXn_1170, // 0x0Bnn
|
||||
PDP11.op0CXn_1170, // 0x0Cnn
|
||||
PDP11.op0DXn_1170, // 0x0Dnn
|
||||
PDP11.opUndefined, // 0x0Enn
|
||||
PDP11.opUndefined // 0x0Fnn
|
||||
];
|
||||
|
||||
PDP11.aOps0AXn_1170 = [
|
||||
PDP11.opCLR, // 0x0A0n
|
||||
PDP11.opCOM, // 0x0A4n
|
||||
PDP11.opINC, // 0x0A8n
|
||||
PDP11.opDEC // 0x0ACn
|
||||
];
|
||||
|
||||
PDP11.aOps0BXn_1170 = [
|
||||
PDP11.opNEG, // 0x0B0n
|
||||
PDP11.opADC, // 0x0B4n
|
||||
PDP11.opSBC, // 0x0B8n
|
||||
PDP11.opTST // 0x0BCn
|
||||
];
|
||||
|
||||
PDP11.aOps0CXn_1170 = [
|
||||
PDP11.opROR, // 0x0C0n
|
||||
PDP11.opROL, // 0x0C4n
|
||||
PDP11.opASR, // 0x0C8n
|
||||
PDP11.opASL // 0x0CCn
|
||||
];
|
||||
|
||||
PDP11.aOps0DXn_1170 = [
|
||||
PDP11.opMARK, // 0x0D0n
|
||||
PDP11.opMFPI, // 0x0D4n
|
||||
PDP11.opMTPI, // 0x0D8n
|
||||
PDP11.opSXT // 0x0DCn
|
||||
];
|
||||
|
||||
PDP11.aOps00Xn_1170 = [
|
||||
PDP11.op000X_1170, // 0x000n
|
||||
PDP11.opUndefined, // 0x001n
|
||||
|
|
@ -1914,13 +1943,13 @@ PDP11.aOps00BX_1170 = [
|
|||
];
|
||||
|
||||
PDP11.aOps000X_1170 = [
|
||||
PDP11.opHALT, // 0x0000
|
||||
PDP11.opWAIT, // 0x0001
|
||||
PDP11.opRTI, // 0x0002
|
||||
PDP11.opBPT, // 0x0003
|
||||
PDP11.opIOT, // 0x0004
|
||||
PDP11.opRESET, // 0x0005
|
||||
PDP11.opRTT, // 0x0006
|
||||
PDP11.opHALT, // 0x0000 000000
|
||||
PDP11.opWAIT, // 0x0001 000001
|
||||
PDP11.opRTI, // 0x0002 000002
|
||||
PDP11.opBPT, // 0x0003 000003
|
||||
PDP11.opIOT, // 0x0004 000004
|
||||
PDP11.opRESET, // 0x0005 000005
|
||||
PDP11.opRTT, // 0x0006 000006
|
||||
PDP11.opUndefined, // 0x0007
|
||||
PDP11.opUndefined, // 0x0008
|
||||
PDP11.opUndefined, // 0x0009
|
||||
|
|
@ -1970,34 +1999,6 @@ PDP11.aOps8Xnn_1170 = [
|
|||
PDP11.opUndefined // 0x8Fnn
|
||||
];
|
||||
|
||||
PDP11.aOps0AXn_1170 = [
|
||||
PDP11.opCLR, // 0x0A0n
|
||||
PDP11.opCOM, // 0x0A4n
|
||||
PDP11.opINC, // 0x0A8n
|
||||
PDP11.opDEC // 0x0ACn
|
||||
];
|
||||
|
||||
PDP11.aOps0BXn_1170 = [
|
||||
PDP11.opNEG, // 0x0B0n
|
||||
PDP11.opADC, // 0x0B4n
|
||||
PDP11.opSBC, // 0x0B8n
|
||||
PDP11.opTST // 0x0BCn
|
||||
];
|
||||
|
||||
PDP11.aOps0CXn_1170 = [
|
||||
PDP11.opROR, // 0x0C0n
|
||||
PDP11.opROL, // 0x0C4n
|
||||
PDP11.opASR, // 0x0C8n
|
||||
PDP11.opASL // 0x0CCn
|
||||
];
|
||||
|
||||
PDP11.aOps0DXn_1170 = [
|
||||
PDP11.opMARK, // 0x0D0n
|
||||
PDP11.opMFPI, // 0x0D4n
|
||||
PDP11.opMTPI, // 0x0D8n
|
||||
PDP11.opSXT // 0x0DCn
|
||||
];
|
||||
|
||||
PDP11.aOps8AXn_1170 = [
|
||||
PDP11.opCLRB, // 0x8A0n
|
||||
PDP11.opCOMB, // 0x8A4n
|
||||
|
|
|
|||
|
|
@ -165,7 +165,6 @@ 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
|
||||
];
|
||||
this.regOp = -1; // current opcode
|
||||
this.opFlags = 0;
|
||||
this.cpuType = 70;
|
||||
this.trapPSW = -1;
|
||||
|
|
@ -504,6 +503,19 @@ CPUStatePDP11.prototype.getPC = function()
|
|||
return this.regsGen[7];
|
||||
};
|
||||
|
||||
/**
|
||||
* getPCWord()
|
||||
*
|
||||
* @this {CPUStatePDP11}
|
||||
* @return {number}
|
||||
*/
|
||||
CPUStatePDP11.prototype.getPCWord = function()
|
||||
{
|
||||
var data = this.readWordFromVirtual(this.regsGen[7]);
|
||||
this.regsGen[7] = (this.regsGen[7] + 2) & 0xffff;
|
||||
return data;
|
||||
};
|
||||
|
||||
/**
|
||||
* setPC()
|
||||
*
|
||||
|
|
@ -728,28 +740,10 @@ CPUStatePDP11.prototype.setPSW = function(newPSW)
|
|||
this.regPSW = newPSW;
|
||||
};
|
||||
|
||||
/**
|
||||
* updateNZCFlags(result, overflow)
|
||||
*
|
||||
* NOTE: The V flag is simply zeroed, it is not "updated" based on the result;
|
||||
* however, a specific overflow value may be provided (used by NEG, for example).
|
||||
*
|
||||
* @this {CPUStatePDP11}
|
||||
* @param {number} result
|
||||
* @param {number} [overflow]
|
||||
*/
|
||||
CPUStatePDP11.prototype.updateNZCFlags = function(result, overflow)
|
||||
{
|
||||
if (!(this.opFlags & PDP11.OPFLAG.SKIP_FLAGS)) {
|
||||
this.flagN = this.flagZ = this.flagC = result;
|
||||
this.flagV = overflow || 0;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* updateNZFlags(result)
|
||||
*
|
||||
* NOTE: The V flag is simply zeroed, it is not "updated" based on the result.
|
||||
* NOTE: The V flag is simply zeroed, and the C flag is unchanged.
|
||||
*
|
||||
* @this {CPUStatePDP11}
|
||||
* @param {number} result
|
||||
|
|
@ -762,6 +756,23 @@ CPUStatePDP11.prototype.updateNZFlags = function(result)
|
|||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* updateAllFlags(result, overflow)
|
||||
*
|
||||
* NOTE: The V flag is simply zeroed, unless a specific value is provided (eg, by NEG).
|
||||
*
|
||||
* @this {CPUStatePDP11}
|
||||
* @param {number} result
|
||||
* @param {number} [overflow]
|
||||
*/
|
||||
CPUStatePDP11.prototype.updateAllFlags = function(result, overflow)
|
||||
{
|
||||
if (!(this.opFlags & PDP11.OPFLAG.SKIP_FLAGS)) {
|
||||
this.flagN = this.flagZ = this.flagC = result;
|
||||
this.flagV = overflow || 0;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* updateAddFlags(result, src, dst)
|
||||
*
|
||||
|
|
@ -815,12 +826,26 @@ CPUStatePDP11.prototype.updateIncFlags = function(result, dst)
|
|||
};
|
||||
|
||||
/**
|
||||
* updateLogFlags(result)
|
||||
* updateMulFlags(result)
|
||||
*
|
||||
* @this {CPUStatePDP11}
|
||||
* @param {number} result
|
||||
*/
|
||||
CPUStatePDP11.prototype.updateLogFlags = function(result)
|
||||
CPUStatePDP11.prototype.updateMulFlags = function(result)
|
||||
{
|
||||
this.flagN = result >> 16;
|
||||
this.flagZ = this.flagN | result;
|
||||
this.flagV = 0;
|
||||
this.flagC = (result < -32768 || result > 32767)? 0x10000 : 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* updateShiftFlags(result)
|
||||
*
|
||||
* @this {CPUStatePDP11}
|
||||
* @param {number} result
|
||||
*/
|
||||
CPUStatePDP11.prototype.updateShiftFlags = function(result)
|
||||
{
|
||||
if (!(this.opFlags & PDP11.OPFLAG.SKIP_FLAGS)) {
|
||||
this.flagN = this.flagZ = this.flagC = result;
|
||||
|
|
@ -913,7 +938,7 @@ CPUStatePDP11.prototype.trap = function(vector, reason)
|
|||
|
||||
if (DEBUG && this.dbg) {
|
||||
if (this.messageEnabled(MessagesPDP11.TRAP)) {
|
||||
this.printMessage("trap to vector " + this.dbg.toBase(vector, 0, true) + (reason? " (reason " + reason + ")" : ""), MessagesPDP11.TRAP, true);
|
||||
this.printMessage("trap to vector " + this.dbg.toStrBase(vector, 0, true) + (reason? " (reason " + reason + ")" : ""), MessagesPDP11.TRAP, true);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1319,9 +1344,7 @@ CPUStatePDP11.prototype.getVirtualByMode = function(addressMode, accessFlags)
|
|||
stepSize = 2;
|
||||
virtualAddress = this.regsGen[reg];
|
||||
if (reg !== 7) virtualAddress |= addrDSpace;
|
||||
if ((virtualAddress = this.readWordFromVirtual(virtualAddress)) < 0) {
|
||||
return virtualAddress;
|
||||
}
|
||||
virtualAddress = this.readWordFromVirtual(virtualAddress);
|
||||
// if (reg === 7) LOG_ADDRESS(virtualAddress); // @#n not operational
|
||||
virtualAddress |= addrDSpace;
|
||||
break;
|
||||
|
|
@ -1345,44 +1368,25 @@ CPUStatePDP11.prototype.getVirtualByMode = function(addressMode, accessFlags)
|
|||
stepSize = -2;
|
||||
virtualAddress = (this.regsGen[reg] - 2) & 0xffff;
|
||||
if (reg !== 7) virtualAddress |= addrDSpace;
|
||||
if ((virtualAddress = this.readWordFromVirtual(virtualAddress)) < 0) {
|
||||
return virtualAddress;
|
||||
}
|
||||
virtualAddress |= addrDSpace;
|
||||
virtualAddress = this.readWordFromVirtual(virtualAddress) | addrDSpace;
|
||||
break;
|
||||
|
||||
/*
|
||||
* Mode 6: d(R)
|
||||
*/
|
||||
case 6:
|
||||
if ((virtualAddress = this.readWordFromVirtual(this.regsGen[7])) < 0) {
|
||||
return virtualAddress;
|
||||
}
|
||||
this.regsGen[7] = (this.regsGen[7] + 2) & 0xffff;
|
||||
if (reg < 7) {
|
||||
virtualAddress = (virtualAddress + this.regsGen[reg]) & 0xffff;
|
||||
} else {
|
||||
virtualAddress = (virtualAddress + this.regsGen[reg]) & 0xffff;
|
||||
}
|
||||
return virtualAddress | addrDSpace;
|
||||
virtualAddress = this.getPCWord();
|
||||
virtualAddress = ((virtualAddress + this.regsGen[reg]) & 0xffff) | addrDSpace;
|
||||
return virtualAddress;
|
||||
|
||||
/*
|
||||
* Mode 7: @d(R)
|
||||
*/
|
||||
case 7:
|
||||
if ((virtualAddress = this.readWordFromVirtual(this.regsGen[7])) < 0) {
|
||||
return virtualAddress;
|
||||
}
|
||||
this.regsGen[7] = (this.regsGen[7] + 2) & 0xffff;
|
||||
if (reg < 7) {
|
||||
virtualAddress = (virtualAddress + this.regsGen[reg]) & 0xffff;
|
||||
} else {
|
||||
virtualAddress = (virtualAddress + this.regsGen[reg]) & 0xffff;
|
||||
}
|
||||
if ((virtualAddress = this.readWordFromVirtual(virtualAddress | PDP11.ACCESS.DSPACE)) < 0) {
|
||||
return virtualAddress;
|
||||
}
|
||||
return virtualAddress | addrDSpace;
|
||||
virtualAddress = this.getPCWord();
|
||||
virtualAddress = (virtualAddress + this.regsGen[reg]) & 0xffff;
|
||||
virtualAddress = this.readWordFromVirtual(virtualAddress | PDP11.ACCESS.DSPACE) | addrDSpace;
|
||||
return virtualAddress;
|
||||
}
|
||||
|
||||
this.regsGen[reg] = (this.regsGen[reg] + stepSize) & 0xffff;
|
||||
|
|
@ -1727,7 +1731,7 @@ CPUStatePDP11.prototype.stepCPU = function(nMinCycles)
|
|||
this.checkInterruptQueue();
|
||||
}
|
||||
|
||||
if (!(this.regMMR0 & 0xe000)) {
|
||||
if (!(this.regMMR0 & PDP11.MMR0.ABORT)) {
|
||||
this.regMMR1 = 0;
|
||||
this.regMMR2 = this.regsGen[7];
|
||||
}
|
||||
|
|
@ -1738,22 +1742,7 @@ CPUStatePDP11.prototype.stepCPU = function(nMinCycles)
|
|||
*/
|
||||
this.opFlags = this.regPSW & PDP11.PSW.TF;
|
||||
|
||||
/*
|
||||
* TODO: Determine (later) if this.regOp is a useful (internal) register to maintain;
|
||||
* perhaps it would alleviate lots of opCode parameter-passing. In the meantime, we use
|
||||
* it to detect if our new decode() function has processed (ie, "consumed") the opcode,
|
||||
* by setting it to -1. If it has, then we can skip the older opcode decode logic below.
|
||||
*/
|
||||
var opCode = this.regOp = this.readWordFromVirtual(this.regsGen[7]);
|
||||
if (opCode >= 0) this.regsGen[7] = (this.regsGen[7] + 2) & 0xffff;
|
||||
|
||||
this.decode(opCode);
|
||||
|
||||
if (DEBUG && this.regOp < 0) {
|
||||
this.regsGen[7] = (this.regsGen[7] - 2) & 0xffff;
|
||||
this.println("unimplemented");
|
||||
break;
|
||||
}
|
||||
this.decode(this.getPCWord());
|
||||
|
||||
} while (this.nStepCycles > 0);
|
||||
|
||||
|
|
|
|||
|
|
@ -777,7 +777,7 @@ if (DEBUGGER) {
|
|||
*/
|
||||
DebuggerPDP11.prototype.toStrOffset = function(off)
|
||||
{
|
||||
return this.toBase(off);
|
||||
return this.toStrBase(off);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -1036,9 +1036,82 @@ if (DEBUGGER) {
|
|||
return false;
|
||||
};
|
||||
|
||||
/**
|
||||
* getRegIndex(sReg, off)
|
||||
*
|
||||
* @this {DebuggerPDP11}
|
||||
* @param {string} sReg
|
||||
* @param {number} [off] optional offset into sReg
|
||||
* @return {number} register index, or -1 if not found
|
||||
*/
|
||||
DebuggerPDP11.prototype.getRegIndex = function(sReg, off)
|
||||
{
|
||||
var iReg = -1;
|
||||
sReg = sReg.toUpperCase();
|
||||
switch(sReg) {
|
||||
case "SP":
|
||||
iReg = 6;
|
||||
break;
|
||||
case "PC":
|
||||
iReg = 7;
|
||||
break;
|
||||
default:
|
||||
if (sReg.charAt(0) == "R") {
|
||||
iReg = +sReg.charAt(1);
|
||||
if (iReg < 0 || iReg > 7) iReg = -1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return iReg;
|
||||
};
|
||||
|
||||
/**
|
||||
* getRegName(iReg)
|
||||
*
|
||||
* @this {DebuggerPDP11}
|
||||
* @param {number} iReg
|
||||
* @return {string}
|
||||
*/
|
||||
DebuggerPDP11.prototype.getRegName = function(iReg)
|
||||
{
|
||||
return (iReg < 6? ("R" + iReg) : (iReg == 6? "SP" : "PC"));
|
||||
};
|
||||
|
||||
/**
|
||||
* getRegValue(iReg)
|
||||
*
|
||||
* Register numbers 0-7 are reserved for cpu.regsGen, 8-15 are reserved for cpu.regsAlt,
|
||||
* 16-19 for cpu.regsAltStack, and 20 for regPSW.
|
||||
*
|
||||
* @this {DebuggerPDP11}
|
||||
* @param {number} iReg
|
||||
* @return {number|undefined}
|
||||
*/
|
||||
DebuggerPDP11.prototype.getRegValue = function(iReg)
|
||||
{
|
||||
var value;
|
||||
if (iReg >= 0) {
|
||||
if (iReg < 8) {
|
||||
value = this.cpu.regsGen[iReg];
|
||||
}
|
||||
else if (iReg < 16) {
|
||||
value = this.cpu.regsAlt[iReg-8];
|
||||
}
|
||||
else if (iReg < 20) {
|
||||
value = this.cpu.regsAltStack[iReg-16];
|
||||
}
|
||||
else if (iReg == DebuggerPDP11.REG_PSW) {
|
||||
value = this.cpu.getPSW();
|
||||
}
|
||||
}
|
||||
return value;
|
||||
};
|
||||
|
||||
/**
|
||||
* replaceRegs(s)
|
||||
*
|
||||
* TODO: Implement or eliminate.
|
||||
*
|
||||
* @this {DebuggerPDP11}
|
||||
* @param {string} s
|
||||
* @return {string}
|
||||
|
|
@ -1929,7 +2002,7 @@ if (DEBUGGER) {
|
|||
var sLine = this.toStrAddr(dbgAddrOp) + ":";
|
||||
if (dbgAddrOp.addr !== PDP11.ADDR_INVALID && dbgAddr.addr !== PDP11.ADDR_INVALID) {
|
||||
do {
|
||||
sOpcodes += ' ' + this.toBase(this.getWord(dbgAddrOp, 2));
|
||||
sOpcodes += ' ' + this.toStrBase(this.getWord(dbgAddrOp, 2));
|
||||
if (dbgAddrOp.addr == null) break;
|
||||
} while (dbgAddrOp.addr != dbgAddr.addr);
|
||||
}
|
||||
|
|
@ -1973,20 +2046,20 @@ if (DEBUGGER) {
|
|||
if (opTypeOther == DebuggerPDP11.OP_BRANCH) {
|
||||
disp = ((opCode & 0xff) << 24) >> 23;
|
||||
addr = (dbgAddr.addr + disp) & 0xffff;
|
||||
sOperand = this.toBase(addr);
|
||||
sOperand = this.toStrBase(addr);
|
||||
}
|
||||
else if (opTypeOther == DebuggerPDP11.OP_DSTOFF) {
|
||||
disp = (opCode & 0x3f) << 1;
|
||||
addr = (dbgAddr.addr - disp) & 0xffff;
|
||||
sOperand = this.toBase(addr);
|
||||
sOperand = this.toStrBase(addr);
|
||||
}
|
||||
else if (opTypeOther == DebuggerPDP11.OP_DSTNUM3) {
|
||||
disp = (opCode & 0x7);
|
||||
sOperand = this.toBase(disp, 1);
|
||||
sOperand = this.toStrBase(disp, 1);
|
||||
}
|
||||
else if (opTypeOther == DebuggerPDP11.OP_DSTNUM6) {
|
||||
disp = (opCode & 0x3f);
|
||||
sOperand = this.toBase(disp, 1);
|
||||
sOperand = this.toStrBase(disp, 1);
|
||||
}
|
||||
else {
|
||||
/*
|
||||
|
|
@ -2022,7 +2095,7 @@ if (DEBUGGER) {
|
|||
* When using R7 (aka PC), POST-INCREMENT is known as IMMEDIATE
|
||||
*/
|
||||
wIndex = this.getWord(dbgAddr, 2);
|
||||
sOperand = '#' + this.toBase(wIndex, 0, true);
|
||||
sOperand = '#' + this.toStrBase(wIndex, 0, true);
|
||||
}
|
||||
break;
|
||||
case PDP11.OPMODE.POSTINCD: // 0x3: POST-INCREMENT DEFERRED
|
||||
|
|
@ -2033,7 +2106,7 @@ if (DEBUGGER) {
|
|||
* When using R7 (aka PC), POST-INCREMENT DEFERRED is known as ABSOLUTE
|
||||
*/
|
||||
wIndex = this.getWord(dbgAddr, 2);
|
||||
sOperand = "@#" + this.toBase(wIndex, 0, true);
|
||||
sOperand = "@#" + this.toStrBase(wIndex, 0, true);
|
||||
}
|
||||
break;
|
||||
case PDP11.OPMODE.PREDEC: // 0x4: PRE-DECREMENT
|
||||
|
|
@ -2044,22 +2117,22 @@ if (DEBUGGER) {
|
|||
break;
|
||||
case PDP11.OPMODE.INDEX: // 0x6: INDEX
|
||||
wIndex = this.getWord(dbgAddr, 2);
|
||||
sOperand = this.toBase(wIndex, 0, true) + '(' + this.getRegName(reg) + ')';
|
||||
sOperand = this.toStrBase(wIndex, 0, true) + '(' + this.getRegName(reg) + ')';
|
||||
if (reg == 7) {
|
||||
/*
|
||||
* When using R7 (aka PC), INDEX is known as RELATIVE
|
||||
*/
|
||||
sOperand = [sOperand, this.toBase((wIndex + dbgAddr.addr) & 0xffff)];
|
||||
sOperand = [sOperand, this.toStrBase((wIndex + dbgAddr.addr) & 0xffff)];
|
||||
}
|
||||
break;
|
||||
case PDP11.OPMODE.INDEXD: // 0x7: INDEX DEFERRED
|
||||
wIndex = this.getWord(dbgAddr, 2);
|
||||
sOperand = '@' + this.toBase(wIndex) + '(' + this.getRegName(reg) + ')';
|
||||
sOperand = '@' + this.toStrBase(wIndex) + '(' + this.getRegName(reg) + ')';
|
||||
if (reg == 7) {
|
||||
/*
|
||||
* When using R7 (aka PC), INDEX DEFERRED is known as RELATIVE DEFERRED
|
||||
*/
|
||||
sOperand = [sOperand, this.toBase((wIndex + dbgAddr.addr) & 0xffff)];
|
||||
sOperand = [sOperand, this.toStrBase((wIndex + dbgAddr.addr) & 0xffff)];
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
|
@ -2122,18 +2195,6 @@ if (DEBUGGER) {
|
|||
return sFlag.charAt(0) + (b? '1' : '0') + ' ';
|
||||
};
|
||||
|
||||
/**
|
||||
* getRegName(iReg)
|
||||
*
|
||||
* @this {DebuggerPDP11}
|
||||
* @param {number} iReg
|
||||
* @return {string}
|
||||
*/
|
||||
DebuggerPDP11.prototype.getRegName = function(iReg)
|
||||
{
|
||||
return (iReg < 6? ("R" + iReg) : (iReg == 6? "SP" : "PC"));
|
||||
};
|
||||
|
||||
/**
|
||||
* getRegOutput(iReg)
|
||||
*
|
||||
|
|
@ -2148,16 +2209,16 @@ if (DEBUGGER) {
|
|||
|
||||
if (iReg < 8) {
|
||||
sReg = this.getRegName(iReg);
|
||||
sReg += '=' + this.toBase(cpu.regsGen[iReg]);
|
||||
sReg += '=' + this.toStrBase(cpu.regsGen[iReg]);
|
||||
}
|
||||
else if (iReg < 13) {
|
||||
sReg = "A" + (iReg - 8) + '=' + this.toBase(cpu.regsAlt[iReg - 8]);
|
||||
sReg = "A" + (iReg - 8) + '=' + this.toStrBase(cpu.regsAlt[iReg - 8]);
|
||||
}
|
||||
else if (iReg >= 16 && iReg < 20) {
|
||||
sReg = "S" + (iReg - 16) + '=' + this.toBase(cpu.regsAltStack[iReg - 16]);
|
||||
sReg = "S" + (iReg - 16) + '=' + this.toStrBase(cpu.regsAltStack[iReg - 16]);
|
||||
}
|
||||
else if (iReg == DebuggerPDP11.REG_PSW) {
|
||||
sReg = "PS=" + this.toBase(cpu.getPSW());
|
||||
sReg = "PS=" + this.toStrBase(cpu.getPSW());
|
||||
}
|
||||
if (sReg) sReg += ' ';
|
||||
return sReg;
|
||||
|
|
@ -2762,29 +2823,32 @@ if (DEBUGGER) {
|
|||
*/
|
||||
DebuggerPDP11.prototype.doEdit = function(asArgs)
|
||||
{
|
||||
var size = 1;
|
||||
var mask = 0xff;
|
||||
var fnGet = this.getByte;
|
||||
var fnSet = this.setByte;
|
||||
if (asArgs[0] == "ew") {
|
||||
var size, mask;
|
||||
var fnGet, fnSet;
|
||||
var sCmd = asArgs[0];
|
||||
var sAddr = asArgs[1];
|
||||
if (sCmd == "eb") {
|
||||
size = 1;
|
||||
mask = 0xff;
|
||||
fnGet = this.getByte;
|
||||
fnSet = this.setByte;
|
||||
}
|
||||
else if (sCmd == "e" || sCmd == "ew") {
|
||||
size = 2;
|
||||
mask = 0xffff;
|
||||
fnGet = this.getWord;
|
||||
fnSet = this.setWord;
|
||||
} else {
|
||||
sAddr = null;
|
||||
}
|
||||
var cch = size << 1;
|
||||
|
||||
var sAddr = asArgs[1];
|
||||
if (sAddr == null) {
|
||||
this.println("edit memory commands:");
|
||||
this.println("\teb [a] [...] edit bytes at address a");
|
||||
this.println("\tew [a] [...] edit words at address a");
|
||||
return;
|
||||
}
|
||||
|
||||
var dbgAddr = this.parseAddr(sAddr);
|
||||
if (!dbgAddr) return;
|
||||
|
||||
for (var i = 2; i < asArgs.length; i++) {
|
||||
var vNew = this.parseExpression(asArgs[i]);
|
||||
if (vNew === undefined) {
|
||||
|
|
@ -2795,7 +2859,7 @@ if (DEBUGGER) {
|
|||
this.println("warning: " + str.toHex(vNew) + " exceeds " + size + "-byte value");
|
||||
}
|
||||
var vOld = fnGet.call(this, dbgAddr);
|
||||
this.println("changing " + this.toStrAddr(dbgAddr) + " from " + str.toHex(vOld, cch, true) + " to " + str.toHex(vNew, cch, true));
|
||||
this.println("changing " + this.toStrAddr(dbgAddr) + " from " + this.toStrBase(vOld, size) + " to " + this.toStrBase(vNew, size));
|
||||
fnSet.call(this, dbgAddr, vNew, size);
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -281,7 +281,8 @@ var PDP11 = {
|
|||
TRAP_MMU: 0x1000, // trap: MMU
|
||||
ABORT_RO: 0x2000, // abort: read-only
|
||||
ABORT_PL: 0x4000, // abort: page length
|
||||
ABORT_NR: 0x8000 // abort: non-resident
|
||||
ABORT_NR: 0x8000, // abort: non-resident
|
||||
ABORT: 0xE000
|
||||
},
|
||||
MMR1: { // general purpose auto-inc/auto-dec register
|
||||
REG1_NUM: 0x0007,
|
||||
|
|
|
|||
|
|
@ -659,7 +659,7 @@ if (DEBUGGER) {
|
|||
};
|
||||
|
||||
/**
|
||||
* toBase(n, nBytes, fStripLeadingZeros)
|
||||
* toStrBase(n, nBytes, fStripLeadingZeros)
|
||||
*
|
||||
* Use this instead of str.toHex() or str.toOct() to convert bytes/words to the Debugger's default base.
|
||||
*
|
||||
|
|
@ -669,7 +669,7 @@ if (DEBUGGER) {
|
|||
* @param {boolean} [fStripLeadingZeros]
|
||||
* @return {string}
|
||||
*/
|
||||
Debugger.prototype.toBase = function(n, nBytes, fStripLeadingZeros)
|
||||
Debugger.prototype.toStrBase = function(n, nBytes, fStripLeadingZeros)
|
||||
{
|
||||
var s;
|
||||
switch(this.nBase) {
|
||||
|
|
|
|||
Loading…
Reference in a new issue