Cleaned up the decoding SRCMODE and DSTMODE operands, should be less confusing now

This commit is contained in:
Jeff 2016-10-04 17:22:25 -07:00 committed by Jeff Parsons
commit 795d57839b
6 changed files with 569 additions and 567 deletions

View file

@ -461,7 +461,7 @@ PDP11.fnXOR = function(src, dst)
*/
PDP11.opADC = function(opCode)
{
this.updateWordByMode(opCode, this.getCF()? 1 : 0, PDP11.fnADD);
this.updateDstWord(opCode, this.getCF()? 1 : 0, PDP11.fnADD);
this.nStepCycles -= (this.dstMode? (8 + 1) : (2 + 1) + (this.dstReg == 7? 2 : 0));
};
@ -473,7 +473,7 @@ PDP11.opADC = function(opCode)
*/
PDP11.opADCB = function(opCode)
{
this.updateByteByMode(opCode, this.getCF()? 1 : 0, PDP11.fnADDB);
this.updateDstByte(opCode, this.getCF()? 1 : 0, PDP11.fnADDB);
this.nStepCycles -= (this.dstMode? (8 + 1) : (2 + 1) + (this.dstReg == 7? 2 : 0));
};
@ -485,7 +485,7 @@ PDP11.opADCB = function(opCode)
*/
PDP11.opADD = function(opCode)
{
this.updateWordByMode(opCode, this.readWordByMode(opCode >> PDP11.SRCMODE.SHIFT), PDP11.fnADD);
this.updateDstWord(opCode, this.readSrcWord(opCode), PDP11.fnADD);
this.nStepCycles -= (this.dstMode? (8 + 1) + (this.srcReg && this.dstReg >= 6? 1 : 0) : (this.srcMode? (3 + 2) : (2 + 1)) + (this.dstReg == 7? 2 : 0));
};
@ -497,11 +497,7 @@ PDP11.opADD = function(opCode)
*/
PDP11.opASH = function(opCode)
{
/*
* NOTE: Because readWordByMode() is being used to READ (not WRITE) the DSTMODE field of opCode,
* this.srcMode and this.srcReg must be used instead of this.dstMode and this.dstReg.
*/
var src = this.readWordByMode(opCode);
var src = this.readDstWord(opCode);
var reg = (opCode >> 6) & 7;
var result = this.regsGen[reg];
if (result & 0x8000) result |= 0xffff0000;
@ -525,7 +521,7 @@ PDP11.opASH = function(opCode)
}
this.regsGen[reg] = result & 0xffff;
this.flagN = this.flagZ = result;
this.nStepCycles -= (this.srcMode? (5 + 1) : (6 + 1)) + src;
this.nStepCycles -= (this.dstMode? (5 + 1) : (6 + 1)) + src;
};
/**
@ -536,11 +532,7 @@ PDP11.opASH = function(opCode)
*/
PDP11.opASHC = function(opCode)
{
/*
* NOTE: Because readWordByMode() is being used to READ (not WRITE) the DSTMODE field of opCode,
* this.srcMode and this.srcReg must be used instead of this.dstMode and this.dstReg.
*/
var src = this.readWordByMode(opCode);
var src = this.readDstWord(opCode);
var reg = (opCode >> 6) & 7;
var dst = (this.regsGen[reg] << 16) | this.regsGen[reg | 1];
this.flagC = this.flagV = 0;
@ -571,7 +563,7 @@ PDP11.opASHC = function(opCode)
this.regsGen[reg | 1] = result & 0xffff;
this.flagN = result >> 16;
this.flagZ = result >> 16 | result;
this.nStepCycles -= (this.srcMode? (5 + 1) : (6 + 1)) + src;
this.nStepCycles -= (this.dstMode? (5 + 1) : (6 + 1)) + src;
};
/**
@ -582,7 +574,7 @@ PDP11.opASHC = function(opCode)
*/
PDP11.opASL = function(opCode)
{
this.updateWordByMode(opCode, 0, PDP11.fnASL);
this.updateDstWord(opCode, 0, PDP11.fnASL);
this.nStepCycles -= (this.dstMode? (8 + 1) : (2 + 1) + (this.dstReg == 7? 2 : 0));
};
@ -594,7 +586,7 @@ PDP11.opASL = function(opCode)
*/
PDP11.opASLB = function(opCode)
{
this.updateByteByMode(opCode, 0, PDP11.fnASLB);
this.updateDstByte(opCode, 0, PDP11.fnASLB);
this.nStepCycles -= (this.dstMode? (8 + 1) : (2 + 1) + (this.dstReg == 7? 2 : 0));
};
@ -606,7 +598,7 @@ PDP11.opASLB = function(opCode)
*/
PDP11.opASR = function(opCode)
{
this.updateWordByMode(opCode, 0, PDP11.fnASR);
this.updateDstWord(opCode, 0, PDP11.fnASR);
this.nStepCycles -= (this.dstMode? (8 + 1) : (2 + 1) + (this.dstReg == 7? 2 : 0));
};
@ -618,7 +610,7 @@ PDP11.opASR = function(opCode)
*/
PDP11.opASRB = function(opCode)
{
this.updateByteByMode(opCode, 0, PDP11.fnASRB);
this.updateDstByte(opCode, 0, PDP11.fnASRB);
this.nStepCycles -= (this.dstMode? (8 + 1) + (this.dstAddr & 1) : (2 + 1) + (this.dstReg == 7? 2 : 0));
};
@ -652,7 +644,7 @@ PDP11.opBCS = function(opCode)
*/
PDP11.opBIC = function(opCode)
{
this.updateWordByMode(opCode, this.readWordByMode(opCode >> PDP11.SRCMODE.SHIFT), PDP11.fnBIC);
this.updateDstWord(opCode, this.readSrcWord(opCode), PDP11.fnBIC);
this.nStepCycles -= (this.dstMode? (8 + 1) + (this.srcReg && this.dstReg >= 6? 1 : 0) : (this.srcMode? (3 + 2) : (2 + 1)) + (this.dstReg == 7? 2 : 0));
};
@ -664,7 +656,7 @@ PDP11.opBIC = function(opCode)
*/
PDP11.opBICB = function(opCode)
{
this.updateByteByMode(opCode, this.readByteByMode(opCode >> PDP11.SRCMODE.SHIFT), PDP11.fnBICB);
this.updateDstByte(opCode, this.readSrcByte(opCode), PDP11.fnBICB);
this.nStepCycles -= (this.dstMode? (8 + 1) + (this.srcReg && this.dstReg >= 6? 1 : 0) : (this.srcMode? (3 + 2) : (2 + 1)) + (this.dstReg == 7? 2 : 0));
};
@ -676,7 +668,7 @@ PDP11.opBICB = function(opCode)
*/
PDP11.opBIS = function(opCode)
{
this.updateWordByMode(opCode, this.readWordByMode(opCode >> PDP11.SRCMODE.SHIFT), PDP11.fnBIS);
this.updateDstWord(opCode, this.readSrcWord(opCode), PDP11.fnBIS);
this.nStepCycles -= (this.dstMode? (8 + 1) + (this.srcReg && this.dstReg >= 6? 1 : 0) : (this.srcMode? (3 + 2) : (2 + 1)) + (this.dstReg == 7? 2 : 0));
};
@ -688,7 +680,7 @@ PDP11.opBIS = function(opCode)
*/
PDP11.opBISB = function(opCode)
{
this.updateByteByMode(opCode, this.readByteByMode(opCode >> PDP11.SRCMODE.SHIFT), PDP11.fnBISB);
this.updateDstByte(opCode, this.readSrcByte(opCode), PDP11.fnBISB);
this.nStepCycles -= (this.dstMode? (8 + 1) + (this.srcReg && this.dstReg >= 6? 1 : 0) : (this.srcMode? (3 + 2) : (2 + 1)) + (this.dstReg == 7? 2 : 0));
};
@ -700,20 +692,8 @@ PDP11.opBISB = function(opCode)
*/
PDP11.opBIT = function(opCode)
{
/*
* NOTE: Because readWordByMode() will be used to READ (not WRITE) the DSTMODE field of opCode,
* the srcMode and srcReg properties need to be copied before they get overwritten.
*/
var src = this.readWordByMode(opCode >> PDP11.SRCMODE.SHIFT);
var srcMode = this.srcMode;
var srcReg = this.srcReg;
/*
* NOTE: Because readWordByMode() is being used to READ (not WRITE) the DSTMODE field of opCode,
* this.srcMode and this.srcReg must be used instead of this.dstMode and this.dstReg.
*/
var dst = this.readWordByMode(opCode);
this.updateNZVFlags(src & dst);
this.nStepCycles -= (this.srcMode? (3 + 1) + (srcReg && this.srcReg >= 6? 1 : 0) : (srcMode? (3 + 1) : (2 + 1)) + (this.srcReg == 7? 2 : 0));
this.updateNZVFlags(this.readSrcWord(opCode) & this.readDstWord(opCode));
this.nStepCycles -= (this.dstMode? (3 + 1) + (this.srcReg && this.dstReg >= 6? 1 : 0) : (this.srcMode? (3 + 1) : (2 + 1)) + (this.dstReg == 7? 2 : 0));
};
/**
@ -724,20 +704,8 @@ PDP11.opBIT = function(opCode)
*/
PDP11.opBITB = function(opCode)
{
/*
* NOTE: Because readByteByMode() will be used to READ (not WRITE) the DSTMODE field of opCode,
* the srcMode and srcReg properties need to be copied before they get overwritten.
*/
var src = this.readByteByMode(opCode >> PDP11.SRCMODE.SHIFT);
var srcMode = this.srcMode;
var srcReg = this.srcReg;
/*
* NOTE: Because readByteByMode() is being used to READ (not WRITE) the DSTMODE field of opCode,
* this.srcMode and this.srcReg must be used instead of this.dstMode and this.dstReg.
*/
var dst = this.readByteByMode(opCode);
this.updateNZVFlags((src & dst) << 8);
this.nStepCycles -= (this.srcMode? (3 + 1) + (srcReg && this.srcReg >= 6? 1 : 0) : (srcMode? (3 + 1) : (2 + 1)) + (this.srcReg == 7? 2 : 0));
this.updateNZVFlags((this.readSrcByte(opCode) & this.readDstByte(opCode)) << 8);
this.nStepCycles -= (this.dstMode? (3 + 1) + (this.srcReg && this.dstReg >= 6? 1 : 0) : (this.srcMode? (3 + 1) : (2 + 1)) + (this.dstReg == 7? 2 : 0));
};
/**
@ -903,7 +871,7 @@ PDP11.opBVS = function(opCode)
*/
PDP11.opCLR = function(opCode)
{
this.updateAllFlags(this.writeWordByMode(opCode, 0));
this.updateAllFlags(this.writeDstWord(opCode, 0));
this.nStepCycles -= (this.dstMode? (8 + 1) : (2 + 1) + (this.dstReg == 7? 2 : 0));
};
@ -915,7 +883,7 @@ PDP11.opCLR = function(opCode)
*/
PDP11.opCLRB = function(opCode)
{
this.updateAllFlags(this.writeByteByMode(opCode, 0));
this.updateAllFlags(this.writeDstByte(opCode, 0));
this.nStepCycles -= (this.dstMode? (8 + 1) : (2 + 1) + (this.dstReg == 7? 2 : 0));
};
@ -993,25 +961,14 @@ PDP11.opCLx = function(opCode)
*/
PDP11.opCMP = function(opCode)
{
/*
* NOTE: Because readWordByMode() will be used to READ (not WRITE) the DSTMODE field of opCode,
* the srcMode and srcReg properties need to be copied before they get overwritten.
*/
var src = this.readWordByMode(opCode >> PDP11.SRCMODE.SHIFT);
var srcMode = this.srcMode;
var srcReg = this.srcReg;
/*
* NOTE: Because readWordByMode() is being used to READ (not WRITE) the DSTMODE field of opCode,
* this.srcMode and this.srcReg must be used instead of this.dstMode and this.dstReg.
*/
var dst = this.readWordByMode(opCode);
var src = this.readSrcWord(opCode);
var dst = this.readDstWord(opCode);
var result = src - dst;
/*
* NOTE: CMP calculates (src - dst) rather than (dst - src), so when we call updateSubFlags(),
* we must reverse the order of the src and dst parameters.
* NOTE: CMP calculates (src - dst) rather than (dst - src), so src and dst updateSubFlags() parms must be reversed.
*/
this.updateSubFlags(result, dst, src);
this.nStepCycles -= (this.srcMode? (3 + 1) + (srcReg && this.srcReg >= 6? 1 : 0) : (srcMode? (3 + 1) : (2 + 1)) + (this.srcReg == 7? 2 : 0));
this.nStepCycles -= (this.dstMode? (3 + 1) + (this.srcReg && this.dstReg >= 6? 1 : 0) : (this.srcMode? (3 + 1) : (2 + 1)) + (this.dstReg == 7? 2 : 0));
};
/**
@ -1022,25 +979,14 @@ PDP11.opCMP = function(opCode)
*/
PDP11.opCMPB = function(opCode)
{
/*
* NOTE: Because readByteByMode() will be used to READ (not WRITE) the DSTMODE field of opCode,
* the srcMode and srcReg properties need to be copied before they get overwritten.
*/
var src = this.readByteByMode(opCode >> PDP11.SRCMODE.SHIFT) << 8;
var srcMode = this.srcMode;
var srcReg = this.srcReg;
/*
* NOTE: Because readByteByMode() is being used to READ (not WRITE) the DSTMODE field of opCode,
* this.srcMode and this.srcReg must be used instead of this.dstMode and this.dstReg.
*/
var dst = this.readByteByMode(opCode) << 8;
var src = this.readSrcByte(opCode) << 8;
var dst = this.readDstByte(opCode) << 8;
var result = src - dst;
/*
* NOTE: CMP calculates (src - dst) rather than (dst - src), so when we call updateSubFlags(),
* we must reverse the order of the src and dst parameters.
* NOTE: CMP calculates (src - dst) rather than (dst - src), so src and dst updateSubFlags() parms must be reversed.
*/
this.updateSubFlags(result, dst, src);
this.nStepCycles -= (this.srcMode? (3 + 1) + (srcReg && this.srcReg >= 6? 1 : 0) : (srcMode? (3 + 1) : (2 + 1)) + (this.srcReg == 7? 2 : 0));
this.nStepCycles -= (this.dstMode? (3 + 1) + (this.srcReg && this.dstReg >= 6? 1 : 0) : (this.srcMode? (3 + 1) : (2 + 1)) + (this.dstReg == 7? 2 : 0));
};
/**
@ -1051,7 +997,7 @@ PDP11.opCMPB = function(opCode)
*/
PDP11.opCOM = function(opCode)
{
this.updateWordByMode(opCode, 0, PDP11.fnCOM);
this.updateDstWord(opCode, 0, PDP11.fnCOM);
this.nStepCycles -= (this.dstMode? (8 + 1) : (2 + 1) + (this.dstReg == 7? 2 : 0));
};
@ -1063,7 +1009,7 @@ PDP11.opCOM = function(opCode)
*/
PDP11.opCOMB = function(opCode)
{
this.updateByteByMode(opCode, 0, PDP11.fnCOMB);
this.updateDstByte(opCode, 0, PDP11.fnCOMB);
this.nStepCycles -= (this.dstMode? (8 + 1) : (2 + 1) + (this.dstReg == 7? 2 : 0));
};
@ -1075,7 +1021,7 @@ PDP11.opCOMB = function(opCode)
*/
PDP11.opDEC = function(opCode)
{
this.updateWordByMode(opCode, 1, PDP11.fnDEC);
this.updateDstWord(opCode, 1, PDP11.fnDEC);
this.nStepCycles -= (this.dstMode? (8 + 1) : (2 + 1) + (this.dstReg == 7? 2 : 0));
};
@ -1087,7 +1033,7 @@ PDP11.opDEC = function(opCode)
*/
PDP11.opDECB = function(opCode)
{
this.updateByteByMode(opCode, 1, PDP11.fnDECB);
this.updateDstByte(opCode, 1, PDP11.fnDECB);
this.nStepCycles -= (this.dstMode? (8 + 1) : (2 + 1) + (this.dstReg == 7? 2 : 0));
};
@ -1102,7 +1048,7 @@ PDP11.opDIV = function(opCode)
/*
* TODO: Review and determine if flag updates can be encapsulated in an updateDivFlags() function.
*/
var src = this.readWordByMode(opCode);
var src = this.readDstWord(opCode);
if (!src) {
this.flagN = 0; // NZVC
this.flagZ = 0;
@ -1169,7 +1115,7 @@ PDP11.opHALT = function(opCode)
*/
PDP11.opINC = function(opCode)
{
this.updateWordByMode(opCode, 1, PDP11.fnINC);
this.updateDstWord(opCode, 1, PDP11.fnINC);
this.nStepCycles -= (this.dstMode? (8 + 1) : (2 + 1) + (this.dstReg == 7? 2 : 0));
};
@ -1181,7 +1127,7 @@ PDP11.opINC = function(opCode)
*/
PDP11.opINCB = function(opCode)
{
this.updateByteByMode(opCode, 1, PDP11.fnINCB);
this.updateDstByte(opCode, 1, PDP11.fnINCB);
this.nStepCycles -= (this.dstMode? (8 + 1) : (2 + 1) + (this.dstReg == 7? 2 : 0));
};
@ -1211,12 +1157,11 @@ PDP11.opJMP = function(opCode)
{
/*
* Since JMP and JSR opcodes have their own unique timings for the various dst modes, we must snapshot
* nStepCycles before decoding the mode, and then use that to update nStepCycles. Moreover, we must use
* srcMode rather than dstMode, because JMP does not WRITE the dst operand; it merely READs it.
* nStepCycles before decoding the mode, and then use that to update nStepCycles.
*/
var nSnapCycles = this.nStepCycles;
this.setPC(this.getVirtualByMode(opCode, PDP11.ACCESS.VIRT));
this.nStepCycles = nSnapCycles - PDP11.JMP_CYCLES[this.srcMode];
this.setPC(this.readDstAddr(opCode));
this.nStepCycles = nSnapCycles - PDP11.JMP_CYCLES[this.dstMode];
};
PDP11.JSR_CYCLES = [
@ -1233,20 +1178,19 @@ PDP11.opJSR = function(opCode)
{
/*
* Since JMP and JSR opcodes have their own unique timings for the various dst modes, we must snapshot
* nStepCycles before decoding the mode, and then use that to update nStepCycles. Moreover, we must use
* srcMode rather than dstMode, because JSR does not WRITE the dst operand; it merely READs it.
* nStepCycles before decoding the mode, and then use that to update nStepCycles.
*/
var nSnapCycles = this.nStepCycles;
/*
* TODO: Determine whether or not the SRCMODE operand (regsGen[reg]) should be snapped BEFORE or AFTER we
* decode the DSTMODE operand. Doing it AFTER seems a bit risky.
*/
var addr = this.getVirtualByMode(opCode, PDP11.ACCESS.VIRT);
var addr = this.readDstAddr(opCode);
var reg = (opCode >> PDP11.SRCMODE.SHIFT) & PDP11.OPREG.MASK;
this.pushWord(this.regsGen[reg]);
this.regsGen[reg] = this.getPC();
this.setPC(addr);
this.nStepCycles = nSnapCycles - PDP11.JSR_CYCLES[this.srcMode];
this.nStepCycles = nSnapCycles - PDP11.JSR_CYCLES[this.dstMode];
};
/**
@ -1310,9 +1254,9 @@ PDP11.opMOV = function(opCode)
* Since MOV opcodes have their own unique timings for the various dst modes, we must snapshot
* nStepCycles after decoding the src mode, and then use that to update nStepCycles.
*/
var data = this.readWordByMode(opCode >> PDP11.SRCMODE.SHIFT);
var data = this.readSrcWord(opCode);
var nSnapCycles = this.nStepCycles;
this.updateNZVFlags(this.writeWordByMode(opCode, data));
this.updateNZVFlags(this.writeDstWord(opCode, data));
this.nStepCycles = nSnapCycles - PDP11.MOV_CYCLES[(this.srcMode? 8 : 0) + this.dstMode] + (this.dstReg == 7 && !this.dstMode? 2 : 0);
};
@ -1324,8 +1268,8 @@ PDP11.opMOV = function(opCode)
*/
PDP11.opMOVB = function(opCode)
{
var data = this.readByteByMode(opCode >> PDP11.SRCMODE.SHIFT);
this.updateNZVFlags(this.writeByteByMode(opCode, data, PDP11.WRITE.SIGNEXT) << 8);
var data = this.readSrcByte(opCode);
this.updateNZVFlags(this.writeDstByte(opCode, data, PDP11.WRITE.SIGNEXT) << 8);
this.nStepCycles -= (this.dstMode? (8 + 1) + (this.srcReg && this.dstReg >= 6? 1 : 0) : (this.srcMode? (3 + 2) : (2 + 1)) + (this.dstReg == 7? 2 : 0));
};
@ -1379,7 +1323,7 @@ PDP11.opMTPI = function(opCode)
*/
PDP11.opMUL = function(opCode)
{
var src = this.readWordByMode(opCode);
var src = this.readDstWord(opCode);
var reg = (opCode >> 6) & 7;
if (src & 0x8000) src |= ~0xffff;
var dst = this.regsGen[reg];
@ -1399,7 +1343,7 @@ PDP11.opMUL = function(opCode)
*/
PDP11.opNEG = function(opCode)
{
this.updateWordByMode(opCode, 0, PDP11.fnNEG);
this.updateDstWord(opCode, 0, PDP11.fnNEG);
this.nStepCycles -= (this.dstMode? (10 + 1) : (5 + 1));
};
@ -1411,7 +1355,7 @@ PDP11.opNEG = function(opCode)
*/
PDP11.opNEGB = function(opCode)
{
this.updateByteByMode(opCode, 0, PDP11.fnNEGB);
this.updateDstByte(opCode, 0, PDP11.fnNEGB);
this.nStepCycles -= (this.dstMode? (10 + 1) : (5 + 1));
};
@ -1450,7 +1394,7 @@ PDP11.opRESET = function(opCode)
*/
PDP11.opROL = function(opCode)
{
this.updateWordByMode(opCode, 0, PDP11.fnROL);
this.updateDstWord(opCode, 0, PDP11.fnROL);
this.nStepCycles -= (this.dstMode? (8 + 1) : (2 + 1) + (this.dstReg == 7? 2 : 0));
};
@ -1462,7 +1406,7 @@ PDP11.opROL = function(opCode)
*/
PDP11.opROLB = function(opCode)
{
this.updateByteByMode(opCode, 0, PDP11.fnROLB);
this.updateDstByte(opCode, 0, PDP11.fnROLB);
this.nStepCycles -= (this.dstMode? (8 + 1) : (2 + 1) + (this.dstReg == 7? 2 : 0));
};
@ -1474,7 +1418,7 @@ PDP11.opROLB = function(opCode)
*/
PDP11.opROR = function(opCode)
{
this.updateWordByMode(opCode, 0, PDP11.fnROR);
this.updateDstWord(opCode, 0, PDP11.fnROR);
this.nStepCycles -= (this.dstMode? (8 + 1) : (2 + 1) + (this.dstReg == 7? 2 : 0));
};
@ -1486,7 +1430,7 @@ PDP11.opROR = function(opCode)
*/
PDP11.opRORB = function(opCode)
{
this.updateByteByMode(opCode, 0, PDP11.fnRORB);
this.updateDstByte(opCode, 0, PDP11.fnRORB);
this.nStepCycles -= (this.dstMode? (8 + 1) + (this.dstAddr & 1) : (2 + 1) + (this.dstReg == 7? 2 : 0));
};
@ -1545,7 +1489,7 @@ PDP11.opRTT = function(opCode)
*/
PDP11.opSBC = function(opCode)
{
this.updateWordByMode(opCode, this.getCF()? 1 : 0, PDP11.fnSUB);
this.updateDstWord(opCode, this.getCF()? 1 : 0, PDP11.fnSUB);
this.nStepCycles -= (this.dstMode? (8 + 1) : (2 + 1) + (this.dstReg == 7? 2 : 0));
};
@ -1557,7 +1501,7 @@ PDP11.opSBC = function(opCode)
*/
PDP11.opSBCB = function(opCode)
{
this.updateByteByMode(opCode, this.getCF()? 1 : 0, PDP11.fnSUBB);
this.updateDstByte(opCode, this.getCF()? 1 : 0, PDP11.fnSUBB);
this.nStepCycles -= (this.dstMode? (8 + 1) : (2 + 1) + (this.dstReg == 7? 2 : 0));
};
@ -1670,7 +1614,7 @@ PDP11.opSPL = function(opCode)
*/
PDP11.opSUB = function(opCode)
{
this.updateWordByMode(opCode, this.readWordByMode(opCode >> PDP11.SRCMODE.SHIFT), PDP11.fnSUB);
this.updateDstWord(opCode, this.readSrcWord(opCode), PDP11.fnSUB);
this.nStepCycles -= (this.dstMode? (8 + 1) + (this.srcReg && this.dstReg >= 6? 1 : 0) : (this.srcMode? (3 + 2) : (2 + 1)) + (this.dstReg == 7? 2 : 0));
};
@ -1682,7 +1626,7 @@ PDP11.opSUB = function(opCode)
*/
PDP11.opSWAB = function(opCode)
{
this.updateWordByMode(opCode, 0, PDP11.fnSWAB);
this.updateDstWord(opCode, 0, PDP11.fnSWAB);
this.nStepCycles -= (this.dstMode? (8 + 1) : (2 + 1) + (this.dstReg == 7? 2 : 0));
};
@ -1694,7 +1638,7 @@ PDP11.opSWAB = function(opCode)
*/
PDP11.opSXT = function(opCode)
{
this.updateNZVFlags(this.writeWordByMode(opCode, this.getNF? 0xffff : 0));
this.updateNZVFlags(this.writeDstWord(opCode, this.getNF? 0xffff : 0));
this.nStepCycles -= (this.dstMode? (8 + 1) : (2 + 1) + (this.dstReg == 7? 2 : 0));
};
@ -1718,14 +1662,10 @@ PDP11.opTRAP = function(opCode)
*/
PDP11.opTST = function(opCode)
{
/*
* NOTE: Because readWordByMode() is being used to READ (not WRITE) the DSTMODE field of opCode,
* this.srcMode and this.srcReg must be used instead of this.dstMode and this.dstReg.
*/
var result = this.readWordByMode(opCode);
var result = this.readDstWord(opCode);
this.assert(!(result & ~0xffff)); // assert that C flag will be clear
this.updateAllFlags(result);
this.nStepCycles -= (this.srcMode? (3 + 1) : (2 + 1) + (this.srcReg == 7? 2 : 0));
this.nStepCycles -= (this.dstMode? (3 + 1) : (2 + 1) + (this.dstReg == 7? 2 : 0));
};
/**
@ -1736,14 +1676,10 @@ PDP11.opTST = function(opCode)
*/
PDP11.opTSTB = function(opCode)
{
/*
* NOTE: Because readByteByMode() is being used to READ (not WRITE) the DSTMODE field of opCode,
* this.srcMode and this.srcReg must be used instead of this.dstMode and this.dstReg.
*/
var result = this.readByteByMode(opCode);
var result = this.readDstByte(opCode);
this.assert(!(result & ~0xff)); // assert that C flag will be clear
this.updateAllFlags(result << 8);
this.nStepCycles -= (this.srcMode? (3 + 1) : (2 + 1) + (this.srcReg == 7? 2 : 0));
this.nStepCycles -= (this.dstMode? (3 + 1) : (2 + 1) + (this.dstReg == 7? 2 : 0));
};
/**
@ -1794,7 +1730,7 @@ PDP11.opWAIT = function(opCode)
*/
PDP11.opXOR = function(opCode)
{
this.updateWordByMode(opCode, this.readWordByMode((opCode & PDP11.SRCMODE.REG) >> PDP11.SRCMODE.SHIFT), PDP11.fnXOR);
this.updateDstWord(opCode, this.readSrcWord(opCode), PDP11.fnXOR);
this.nStepCycles -= (this.dstMode? (8 + 1) : (2 + 1) + (this.dstReg == 7? 2 : 0));
};

View file

@ -172,13 +172,13 @@ CPUStatePDP11.prototype.initRegs = function()
this.opFlags = 0;
/*
* srcMode and srcReg are set by getVirtualByMode() for reads, and dstMode and dstReg are set for writes/updates.
* indicating to the opcode handlers the mode(s) and register(s) used as part of the current opcode, so that they
* can calculate the correct number of cycles. dstAddr is set for byte operations that also need to know the
* effective address for their cycle calculation.
* srcMode and srcReg are set by SRCMODE decodes, and dstMode and dstReg are set for DSTMODE decodes,
* indicating to the opcode handlers the mode(s) and register(s) used as part of the current opcode, so
* that they can calculate the correct number of cycles. dstAddr is set for byte operations that also
* need to know the effective address for their cycle calculation.
*/
this.srcMode = this.dstMode = this.dstAddr = 0;
this.srcReg = this.dstReg = 0;
this.srcMode = this.srcReg = 0;
this.dstMode = this.dstReg = this.dstAddr = 0;
this.cpuType = 70;
this.trapPSW = -1;
@ -1281,9 +1281,9 @@ CPUStatePDP11.prototype.pushWord = function(data)
/**
* getVirtualByMode(addressMode, accessFlags)
* getVirtual(mode, reg, accessFlags)
*
* getVirtualByMode() maps a six bit operand to a 17 bit I/D virtual address space.
* getVirtual() maps a six bit operand to a 17 bit I/D virtual address space.
*
* Instruction operands are six bits in length - three bits for the mode and three
* for the register. The 17th I/D bit in the resulting virtual address represents
@ -1305,24 +1305,16 @@ CPUStatePDP11.prototype.pushWord = function(data)
* if a page fault occurs.
*
* @this {CPUStatePDP11}
* @param {number} addressMode
* @param {number} mode
* @param {number} reg
* @param {number} accessFlags
* @return {number}
*/
CPUStatePDP11.prototype.getVirtualByMode = function(addressMode, accessFlags)
CPUStatePDP11.prototype.getVirtual = function(mode, reg, accessFlags)
{
var virtualAddress, stepSize;
var addrDSpace = (accessFlags & PDP11.ACCESS.VIRT)? 0 : this.addrDSpace;
var mode = (addressMode >> 3) & 7;
var reg = addressMode & PDP11.OPREG.MASK;
if (accessFlags & PDP11.ACCESS.WRITE) {
this.dstMode = mode; this.dstReg = reg;
} else {
this.srcMode = mode; this.srcReg = reg;
}
/*
* Modes that need to auto-increment or auto-decrement will break, in order to perform the
* update; others will return an address immediately.
@ -1331,7 +1323,7 @@ CPUStatePDP11.prototype.getVirtualByMode = function(addressMode, accessFlags)
/*
* Mode 0: Registers don't have a virtual address, so trap.
*
* NOTE: Most instruction code paths never call getVirtualByMode() when the mode is zero;
* NOTE: Most instruction code paths never call getVirtual() when the mode is zero;
* JMP and JSR instructions are exceptions, but that's OK, because those are documented to
* "cause an 'illegal' instruction" condition", which we interpret to mean a BUS_ERROR trap.
*/
@ -1447,31 +1439,31 @@ CPUStatePDP11.prototype.getVirtualByMode = function(addressMode, accessFlags)
};
/**
* getAddrPhysical(addressMode, accessFlags)
* getAddrPhysical(mode, reg, accessFlags)
*
* @this {CPUStatePDP11}
* @param {number} addressMode
* @param {number} mode
* @param {number} reg
* @param {number} accessFlags
* @return {number}
*/
CPUStatePDP11.prototype.getAddrPhysical = function(addressMode, accessFlags)
CPUStatePDP11.prototype.getAddrPhysical = function(mode, reg, accessFlags)
{
this.assert(addressMode & PDP11.OPMODE.MASK);
return this.getVirtualByMode(addressMode, accessFlags);
return this.getVirtual(mode, reg, accessFlags);
};
/**
* getAddrVirtual(addressMode, accessFlags)
* getAddrVirtual(mode, reg, accessFlags)
*
* @this {CPUStatePDP11}
* @param {number} addressMode
* @param {number} mode
* @param {number} reg
* @param {number} accessFlags
* @return {number}
*/
CPUStatePDP11.prototype.getAddrVirtual = function(addressMode, accessFlags)
CPUStatePDP11.prototype.getAddrVirtual = function(mode, reg, accessFlags)
{
this.assert(addressMode & PDP11.OPMODE.MASK);
return this.mapVirtualToPhysical(this.getVirtualByMode(addressMode, accessFlags), accessFlags);
return this.mapVirtualToPhysical(this.getVirtual(mode, reg, accessFlags), accessFlags);
};
/**
@ -1485,16 +1477,16 @@ CPUStatePDP11.prototype.getAddrVirtual = function(addressMode, accessFlags)
CPUStatePDP11.prototype.readWordFromPrevSpace = function(opCode, accessFlags)
{
var src;
if (!(opCode & PDP11.OPMODE.MASK)) {
this.srcMode = 0;
var reg = this.srcReg = opCode & PDP11.OPREG.MASK;
var reg = this.dstReg = opCode & PDP11.OPREG.MASK;
var mode = this.dstMode = (opCode & PDP11.OPMODE.MASK) >> PDP11.OPMODE.SHIFT;
if (!mode) {
if (reg != 6 || ((this.regPSW >> 2) & PDP11.PSW.PMODE) === (this.regPSW & PDP11.PSW.PMODE)) {
src = this.regsGen[reg];
} else {
src = this.regsAltStack[(this.regPSW >> 12) & 3];
}
} else {
var addr = this.getVirtualByMode(opCode, PDP11.ACCESS.READ_WORD);
var addr = this.getVirtual(mode, reg, PDP11.ACCESS.READ_WORD);
if (!(accessFlags & PDP11.ACCESS.DSPACE)) {
if ((this.regPSW & 0xf000) !== 0xf000) addr &= 0xffff;
}
@ -1518,16 +1510,16 @@ CPUStatePDP11.prototype.writeWordToPrevSpace = function(opCode, accessFlags, dat
if (!(this.regMMR0 & 0xe000)) {
this.regMMR1 = 0x16;
}
if (!(opCode & PDP11.OPMODE.MASK)) {
this.dstMode = 0;
var reg = this.dstReg = opCode & PDP11.OPREG.MASK;
var reg = this.dstReg = opCode & PDP11.OPREG.MASK;
var mode = this.dstMode = (opCode & PDP11.OPMODE.MASK) >> PDP11.OPMODE.SHIFT;
if (!mode) {
if (reg != 6 || ((this.regPSW >> 2) & PDP11.PSW.PMODE) === (this.regPSW & PDP11.PSW.PMODE)) {
this.regsGen[reg] = data;
} else {
this.regsAltStack[(this.regPSW >> 12) & 3] = data;
}
} else {
var addr = this.getVirtualByMode(opCode, PDP11.ACCESS.WRITE_WORD);
var addr = this.getVirtual(mode, reg, PDP11.ACCESS.WRITE_WORD);
if (!(accessFlags & PDP11.ACCESS.DSPACE)) addr &= 0xffff;
this.mmuMode = (this.regPSW >> 12) & 3;
addr = this.mapVirtualToPhysical(addr | (accessFlags & PDP11.ACCESS.DSPACE), PDP11.ACCESS.WRITE);
@ -1537,124 +1529,161 @@ CPUStatePDP11.prototype.writeWordToPrevSpace = function(opCode, accessFlags, dat
};
/**
* readWordByMode(addressMode)
* readSrcByte(opCode)
*
* @this {CPUStatePDP11}
* @param {number} addressMode
* @param {number} opCode
* @return {number}
*/
CPUStatePDP11.prototype.readWordByMode = function(addressMode)
CPUStatePDP11.prototype.readSrcByte = function(opCode)
{
var result;
if (!(addressMode & PDP11.OPMODE.MASK)) {
this.srcMode = 0;
result = this.regsGen[this.srcReg = addressMode & PDP11.OPREG.MASK];
opCode >>= PDP11.SRCMODE.SHIFT;
var reg = this.srcReg = opCode & PDP11.OPREG.MASK;
var mode = this.srcMode = (opCode & PDP11.OPMODE.MASK) >> PDP11.OPMODE.SHIFT;
if (!mode) {
result = this.regsGen[reg] & 0xff;
} else {
result = this.readWordFromPhysical(this.getAddr(addressMode, PDP11.ACCESS.READ_WORD));
result = this.readByteFromPhysical(this.getAddr(mode, reg, PDP11.ACCESS.READ_BYTE));
}
return result;
};
/**
* readByteByMode(addressMode)
* readSrcWord(opCode)
*
* @this {CPUStatePDP11}
* @param {number} addressMode
* @param {number} opCode
* @return {number}
*/
CPUStatePDP11.prototype.readByteByMode = function(addressMode)
CPUStatePDP11.prototype.readSrcWord = function(opCode)
{
var result;
if (!(addressMode & PDP11.OPMODE.MASK)) {
this.srcMode = 0;
result = this.regsGen[this.srcReg = addressMode & PDP11.OPREG.MASK] & 0xff;
opCode >>= PDP11.SRCMODE.SHIFT;
var reg = this.srcReg = opCode & PDP11.OPREG.MASK;
var mode = this.srcMode = (opCode & PDP11.OPMODE.MASK) >> PDP11.OPMODE.SHIFT;
if (!mode) {
result = this.regsGen[reg];
} else {
result = this.readByteFromPhysical(this.getAddr(addressMode, PDP11.ACCESS.READ_BYTE));
result = this.readWordFromPhysical(this.getAddr(mode, reg, PDP11.ACCESS.READ_WORD));
}
return result;
};
/**
* updateWordByMode(addressMode, src, fnOp)
*
* Used whenever the dst operand (as described by addressMode) DOES need to be read before writing.
* readDstAddr(opCode)
*
* @this {CPUStatePDP11}
* @param {number} addressMode
* @param {number} src
* @param {function(number,number)} fnOp
* @param {number} opCode
* @return {number}
*/
CPUStatePDP11.prototype.updateWordByMode = function(addressMode, src, fnOp)
CPUStatePDP11.prototype.readDstAddr = function(opCode)
{
if (!(addressMode & PDP11.OPMODE.MASK)) {
this.dstMode = 0;
var reg = this.dstReg = addressMode & PDP11.OPREG.MASK;
this.regsGen[reg] = fnOp.call(this, src, this.regsGen[reg]);
} else {
var addr = this.getAddr(addressMode, PDP11.ACCESS.UPDATE_WORD);
this.writeWordToPhysical(addr, fnOp.call(this, src, this.readWordFromPhysical(addr)));
}
var reg = this.dstReg = opCode & PDP11.OPREG.MASK;
var mode = this.dstMode = (opCode & PDP11.OPMODE.MASK) >> PDP11.OPMODE.SHIFT;
return this.getVirtual(mode, reg, PDP11.ACCESS.VIRT);
};
/**
* updateByteByMode(addressMode, src, fnOp)
*
* Used whenever the dst operand (as described by addressMode) DOES need to be read before writing.
* readDstByte(opCode)
*
* @this {CPUStatePDP11}
* @param {number} addressMode
* @param {number} opCode
* @return {number}
*/
CPUStatePDP11.prototype.readDstByte = function(opCode)
{
var result;
var reg = this.dstReg = opCode & PDP11.OPREG.MASK;
var mode = this.dstMode = (opCode & PDP11.OPMODE.MASK) >> PDP11.OPMODE.SHIFT;
if (!mode) {
result = this.regsGen[reg] & 0xff;
} else {
result = this.readByteFromPhysical(this.getAddr(mode, reg, PDP11.ACCESS.READ_BYTE));
}
return result;
};
/**
* readDstWord(opCode)
*
* @this {CPUStatePDP11}
* @param {number} opCode
* @return {number}
*/
CPUStatePDP11.prototype.readDstWord = function(opCode)
{
var result;
var reg = this.dstReg = opCode & PDP11.OPREG.MASK;
var mode = this.dstMode = (opCode & PDP11.OPMODE.MASK) >> PDP11.OPMODE.SHIFT;
if (!mode) {
result = this.regsGen[reg];
} else {
result = this.readWordFromPhysical(this.getAddr(mode, reg, PDP11.ACCESS.READ_WORD));
}
return result;
};
/**
* updateDstByte(opCode, src, fnOp)
*
* Used whenever the dst operand (as described by opCode) needs to be read before writing.
*
* @this {CPUStatePDP11}
* @param {number} opCode
* @param {number} src
* @param {function(number,number)} fnOp
*/
CPUStatePDP11.prototype.updateByteByMode = function(addressMode, src, fnOp)
CPUStatePDP11.prototype.updateDstByte = function(opCode, src, fnOp)
{
if (!(addressMode & PDP11.OPMODE.MASK)) {
this.dstMode = 0;
var reg = this.dstReg = addressMode & PDP11.OPREG.MASK;
var reg = this.dstReg = opCode & PDP11.OPREG.MASK;
var mode = this.dstMode = (opCode & PDP11.OPMODE.MASK) >> PDP11.OPMODE.SHIFT;
if (!mode) {
this.regsGen[reg] = (this.regsGen[reg] & 0xff00) | fnOp.call(this, src, this.regsGen[reg]);
} else {
var addr = this.dstAddr = this.getAddr(addressMode, PDP11.ACCESS.UPDATE_BYTE);
var addr = this.dstAddr = this.getAddr(mode, reg, PDP11.ACCESS.UPDATE_BYTE);
this.writeByteToPhysical(addr, fnOp.call(this, src, this.readByteFromPhysical(addr)));
}
};
/**
* writeWordByMode(addressMode, data)
* updateDstWord(opCode, src, fnOp)
*
* Used whenever the dst operand (as described by addressMode) does NOT need to be read before writing.
* Used whenever the dst operand (as described by opCode) needs to be read before writing.
*
* @this {CPUStatePDP11}
* @param {number} addressMode
* @param {number} data
* @return {number}
* @param {number} opCode
* @param {number} src
* @param {function(number,number)} fnOp
*/
CPUStatePDP11.prototype.writeWordByMode = function(addressMode, data)
CPUStatePDP11.prototype.updateDstWord = function(opCode, src, fnOp)
{
if (!(addressMode & PDP11.OPMODE.MASK)) {
this.dstMode = 0;
this.regsGen[this.dstReg = addressMode & PDP11.OPREG.MASK] = data & 0xffff;
var reg = this.dstReg = opCode & PDP11.OPREG.MASK;
var mode = this.dstMode = (opCode & PDP11.OPMODE.MASK) >> PDP11.OPMODE.SHIFT;
if (!mode) {
this.regsGen[reg] = fnOp.call(this, src, this.regsGen[reg]);
} else {
this.writeWordToPhysical(this.getAddr(addressMode, PDP11.ACCESS.WRITE_WORD), data);
var addr = this.getAddr(mode, reg, PDP11.ACCESS.UPDATE_WORD);
this.writeWordToPhysical(addr, fnOp.call(this, src, this.readWordFromPhysical(addr)));
}
return data;
};
/**
* writeByteByMode(addressMode, data, writeFlags)
* writeDstByte(opCode, data, writeFlags)
*
* Used whenever the dst operand (as described by addressMode) does NOT need to be read before writing.
* Used whenever the dst operand (as described by opCode) does NOT need to be read before writing.
*
* @this {CPUStatePDP11}
* @param {number} addressMode
* @param {number} opCode
* @param {number} data
* @param {number} [writeFlags]
* @return {number}
*/
CPUStatePDP11.prototype.writeByteByMode = function(addressMode, data, writeFlags)
CPUStatePDP11.prototype.writeDstByte = function(opCode, data, writeFlags)
{
if (!(addressMode & PDP11.OPMODE.MASK)) {
this.dstMode = 0;
var reg = this.dstReg = addressMode & PDP11.OPREG.MASK;
var reg = this.dstReg = opCode & PDP11.OPREG.MASK;
var mode = this.dstMode = (opCode & PDP11.OPMODE.MASK) >> PDP11.OPMODE.SHIFT;
if (!mode) {
if (!data) {
this.regsGen[reg] &= ~0xff; // TODO: Profile to determine if this is a win
} else if (writeFlags & PDP11.WRITE.SIGNEXT) {
@ -1663,7 +1692,29 @@ CPUStatePDP11.prototype.writeByteByMode = function(addressMode, data, writeFlags
this.regsGen[reg] = (this.regsGen[reg] & ~0xff) | (data & 0xff);
}
} else {
this.writeByteToPhysical(this.getAddr(addressMode, PDP11.ACCESS.WRITE_BYTE), data);
this.writeByteToPhysical(this.getAddr(mode, reg, PDP11.ACCESS.WRITE_BYTE), data);
}
return data;
};
/**
* writeDstWord(opCode, data)
*
* Used whenever the dst operand (as described by opCode) does NOT need to be read before writing.
*
* @this {CPUStatePDP11}
* @param {number} opCode
* @param {number} data
* @return {number}
*/
CPUStatePDP11.prototype.writeDstWord = function(opCode, data)
{
var reg = this.dstReg = opCode & PDP11.OPREG.MASK;
var mode = this.dstMode = (opCode & PDP11.OPMODE.MASK) >> PDP11.OPMODE.SHIFT;
if (!mode) {
this.regsGen[reg] = data & 0xffff;
} else {
this.writeWordToPhysical(this.getAddr(mode, reg, PDP11.ACCESS.WRITE_WORD), data);
}
return data;
};

View file

@ -589,6 +589,9 @@ if (DEBUGGER) {
var addr = this.getAddr(dbgAddr, false, 1);
if (addr !== PDP11.ADDR_INVALID) {
this.nDisableMessages++;
/*
* TODO: We also need a Bus interface to disable fnAccess() calls that could trigger a trap()
*/
b = this.bus.getByteDirect(addr);
this.nDisableMessages--;
if (inc) this.incAddr(dbgAddr, inc);
@ -610,6 +613,9 @@ if (DEBUGGER) {
var addr = this.getAddr(dbgAddr, false, 2);
if (addr !== PDP11.ADDR_INVALID) {
this.nDisableMessages++;
/*
* TODO: We also need a Bus interface to disable fnAccess() calls that could trigger a trap()
*/
w = this.bus.getWordDirect(addr);
this.nDisableMessages--;
if (inc) this.incAddr(dbgAddr, inc);
@ -630,6 +636,9 @@ if (DEBUGGER) {
var addr = this.getAddr(dbgAddr, true, 1);
if (addr !== PDP11.ADDR_INVALID) {
this.nDisableMessages++;
/*
* TODO: We also need a Bus interface to disable fnAccess() calls that could trigger a trap()
*/
this.bus.setByteDirect(addr, b);
this.nDisableMessages--;
if (inc) this.incAddr(dbgAddr, inc);
@ -650,6 +659,9 @@ if (DEBUGGER) {
var addr = this.getAddr(dbgAddr, true, 2);
if (addr !== PDP11.ADDR_INVALID) {
this.nDisableMessages++;
/*
* TODO: We also need a Bus interface to disable fnAccess() calls that could trigger a trap()
*/
this.bus.setWordDirect(addr, w);
this.nDisableMessages--;
if (inc) this.incAddr(dbgAddr, inc);
@ -3425,7 +3437,7 @@ if (DEBUGGER) {
}
}
}
addr--;
addr -= 2;
}
dbgAddr.addr = addrOrig;
return sCall;
@ -3463,6 +3475,7 @@ if (DEBUGGER) {
* wrap the offset around the end of the segment, we must also check the addr property to detect the wrap.
*/
if (dbgAddrStack.addr == null || !cTests--) break;
if (dbgAddrCall.addr & 0x1) continue; // an odd address on the PDP-11 is not a valid instruction boundary
sCall = this.getCall(dbgAddrCall);
if (sCall) break;
}

View file

@ -189,7 +189,8 @@ var PDP11 = {
PREDECD: 0x28, // AUTO-DECREMENT DEFERRED (register decremented, register is address of address of operand)
INDEX: 0x30, // INDEX (register + next word is address of operand)
INDEXD: 0x38, // INDEX DEFERRED (register + next word is address of address of operand)
MASK: 0x38
MASK: 0x38,
SHIFT: 3
},
DSTMODE: {
REG: 0x0007,