DEC's "TRAP TEST" finally passes (and I learned a lot about PDP-11 opcode idiosyncrasies in the process)

This commit is contained in:
Jeff 2016-11-12 12:54:13 -08:00 committed by Jeff Parsons
commit 2c1191ce6e
14 changed files with 616 additions and 518 deletions

View file

@ -693,7 +693,9 @@ PDP11.opBISB = function(opCode)
*/
PDP11.opBIT = function(opCode)
{
this.updateNZVFlags(this.readSrcWord(opCode) & this.readDstWord(opCode));
var src = this.readSrcWord(opCode);
var dst = this.readDstWord(opCode);
this.updateNZVFlags((src < 0? this.regsGen[-src-1] : src) & dst);
this.nStepCycles -= (this.dstMode? (3 + 1) + (this.srcReg && this.dstReg >= 6? 1 : 0) : (this.srcMode? (3 + 1) : (2 + 1)) + (this.dstReg == 7? 2 : 0));
};
@ -705,7 +707,9 @@ PDP11.opBIT = function(opCode)
*/
PDP11.opBITB = function(opCode)
{
this.updateNZVFlags((this.readSrcByte(opCode) & this.readDstByte(opCode)) << 8);
var src = this.readSrcByte(opCode);
var dst = this.readDstByte(opCode);
this.updateNZVFlags(((src < 0? (this.regsGen[-src-1] & 0xff) : src) & dst) << 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));
};
@ -964,7 +968,7 @@ PDP11.opCMP = function(opCode)
{
var src = this.readSrcWord(opCode);
var dst = this.readDstWord(opCode);
var result = src - dst;
var result = (src = (src < 0? this.regsGen[-src-1] : src)) - dst;
/*
* NOTE: CMP calculates (src - dst) rather than (dst - src), so src and dst updateSubFlags() parms must be reversed.
*/
@ -980,9 +984,9 @@ PDP11.opCMP = function(opCode)
*/
PDP11.opCMPB = function(opCode)
{
var src = this.readSrcByte(opCode) << 8;
var dst = this.readDstByte(opCode) << 8;
var result = src - dst;
var src = this.readSrcByte(opCode);
var dst = this.readDstByte(opCode);
var result = (src = (src < 0? (this.regsGen[-src-1] & 0xff): src) << 8) - (dst <<= 8);
/*
* NOTE: CMP calculates (src - dst) rather than (dst - src), so src and dst updateSubFlags() parms must be reversed.
*/
@ -1667,7 +1671,7 @@ PDP11.opSPL = function(opCode)
}
if (!(this.regPSW & PDP11.PSW.CMODE)) {
this.regPSW = (this.regPSW & ~(PDP11.PSW.UNUSED | PDP11.PSW.PRI)) | ((opCode & 0x7) << PDP11.PSW.SHIFT.PRI);
this.opFlags |= PDP11.OPFLAG.INTQ_SPL;
this.opFlags |= PDP11.OPFLAG.INTQ_CHK;
}
this.nStepCycles -= (4 + 1);
};

View file

@ -242,6 +242,10 @@ CPUStatePDP11.prototype.resetRegs = function()
this.mmuEnable = 0; // MMU enabled for PDP11.ACCESS.READ or PDP11.ACCESS.WRITE
this.mmuLastMode = 0;
this.mmuMask = 0x3ffff;
this.lastAI = 0; // last auto-incs and/or auto-decs; this gets propagated to MMR1
this.lastPC = 0; // last PC at the time of getOpcode(); this get propagated to MMR2
this.resetTriggers();
if (this.bus) this.setMemoryAccess();
@ -324,6 +328,9 @@ CPUStatePDP11.prototype.setMMR0 = function(newMMR0)
*/
CPUStatePDP11.prototype.getMMR1 = function()
{
if (!(this.regMMR0 & PDP11.MMR0.ABORT)) {
this.regMMR1 = this.lastAI & 0xffff;
}
var result = this.regMMR1;
if (result & 0xff00) {
result = ((result << 8) | (result >> 8)) & 0xffff;
@ -331,6 +338,20 @@ CPUStatePDP11.prototype.getMMR1 = function()
return result;
};
/**
* getMMR2()
*
* @this {CPUStatePDP11}
* @return {number}
*/
CPUStatePDP11.prototype.getMMR2 = function()
{
if (!(this.regMMR0 & PDP11.MMR0.ABORT)) {
this.regMMR2 = this.lastPC;
}
return this.regMMR2;
};
/**
* getMMR3()
*
@ -560,21 +581,22 @@ CPUStatePDP11.prototype.setNF = function()
/**
* getOpcode()
*
* TODO: Determine whether we can speed this up by *always* snapping PC into a shadow MMR2 register
* and eliminating the ABORT test.
*
* @this {CPUStatePDP11}
* @return {number}
*/
CPUStatePDP11.prototype.getOpcode = function()
{
var pc = this.regsGen[PDP11.REG.PC];
if (!(this.regMMR0 & PDP11.MMR0.ABORT)) {
this.regMMR1 = 0;
this.regMMR2 = pc;
}
this.lastAI = 0;
this.lastPC = pc;
/*
* If PC is misaligned, a BUS_ERROR trap will be generated, and because it will generate an
* exception, the next line (the equivalent of advancePC(2)) will not be executed, ensuring that
* original misaligned PC will be pushed onto the stack by trap().
*/
var op = this.readWord(pc);
this.regsGen[PDP11.REG.PC] = (pc + 2) & 0xffff;
return this.readWord(pc);
return op;
};
/**
@ -614,10 +636,7 @@ CPUStatePDP11.prototype.getPC = function()
*/
CPUStatePDP11.prototype.getLastPC = function()
{
/*
* As long as we're always snapping the PC into regMMR2 before every opcode, we might as well use it.
*/
return this.regMMR2;
return this.lastPC;
};
/**
@ -800,10 +819,10 @@ CPUStatePDP11.prototype.checkInterrupts = function()
fInterrupt = true;
}
}
else if (this.opFlags & PDP11.OPFLAG.INTQ_SPL) {
else if (this.opFlags & PDP11.OPFLAG.INTQ_CHK) {
/*
* We know that INTQ (bit 1) is clear, so since INTQ_SPL (bit 0) is set, incrementing opFlags
* will transform INTQ_SPL into INTQ, without affecting any other (higher) bits.
* We know that INTQ (bit 1) is clear, so since INTQ_CHK (bit 0) is set, incrementing opFlags
* will transform INTQ_CHK into INTQ, without affecting any other (higher) bits.
*/
this.opFlags++;
}
@ -1246,10 +1265,8 @@ CPUStatePDP11.prototype.trap = function(vector, flag, reason)
this.regsGen[6] = 4;
}
if (!(this.regMMR0 & PDP11.MMR0.ABORT)) {
this.regMMR1 = 0xf6f6;
this.regMMR2 = vector;
}
this.lastPC = vector;
this.lastAI = 0;
/*
* Read from kernel D space
@ -1273,8 +1290,32 @@ CPUStatePDP11.prototype.trap = function(vector, flag, reason)
* only want to "lose interest" in the TRAP flag(s) that were set on entry, not ALL of them.
*
* this.opFlags &= ~PDP11.OPFLAG.TRAP_MASK; // lose interest in traps after an abort
*
* Well, OK, we're also supposed to "lose interest" in the TF flag, too; otherwise, DEC tests fail.
*
* Finally, setPSW() likes to always set INTQ, to force a check of hardware interrupts prior to
* the next instruction, just in case the PSW priority was lowered. However, there are "TRAP TEST"
* tests like this one:
*
* 005640: 012706 007700 MOV #7700,SP
* 005644: 012767 000340 172124 MOV #340,177776
* 005652: 012767 000100 171704 MOV #100,177564
* 005660: 012767 005712 172146 MOV #5712,000034 ; set TRAP vector (its PSW is already zero)
* 005666: 012767 005714 172170 MOV #5714,000064 ; set hardware interrupt vector (its PSW is already zero)
* 005674: 012767 005716 172116 MOV #5716,000020 ; set IOT vector
* 005702: 012767 000340 172112 MOV #340,000022 ; set IOT PSW
* 005710: 104400 TRAP 000
* 005712: 000004 IOT
* 005714: 000000 HALT
*
* where, after "TRAP 000" has executed, a hardware interrupt will be acknowledged, and instead of
* executing the IOT, we'll execute the HALT and fail the test. We avoid that by relying on the same
* trick that the SPL instruction uses: setting INTQ_CHK instead of INTQ, which effectively delays
* INTQ detection for one instruction, which is just long enough to allow the diagnostic to pass.
*/
this.opFlags &= ~flag;
this.opFlags &= ~(flag | PDP11.OPFLAG.TRAP_TF | PDP11.OPFLAG.INTQ);
this.opFlags |= PDP11.OPFLAG.INTQ_CHK;
this.trapPSW = -1; // reset flag that we have a trap within a trap
/*
@ -1543,7 +1584,7 @@ CPUStatePDP11.prototype.readByteFromPhysical = function(physicalAddress)
CPUStatePDP11.prototype.writeByteToPhysical = function(physicalAddress, data)
{
if (physicalAddress & 1) this.nStepCycles--;
this.bus.setByte(physicalAddress, data & 0xff);
this.bus.setByte(physicalAddress, data);
};
/**
@ -1568,12 +1609,8 @@ CPUStatePDP11.prototype.popWord = function()
CPUStatePDP11.prototype.pushWord = function(data)
{
var virtualAddress = (this.regsGen[6] - 2) & 0xffff;
this.regsGen[6] = virtualAddress; // BSD needs SP updated before any fault :-(
if (!(this.regMMR0 & 0xe000)) {
this.regMMR1 = (this.regMMR1 << 8) | 0xf6;
}
this.lastAI = (this.lastAI << 8) | 0xf6;
this.checkStackLimit(0, virtualAddress);
this.writeWord(virtualAddress, data);
};
@ -1658,7 +1695,7 @@ CPUStatePDP11.prototype.checkStackLimit = function(mode, addr)
*/
CPUStatePDP11.prototype.getAddrByMode = function(mode, reg, accessFlags)
{
var virtualAddress, stepSize;
var virtualAddress, step;
var addrDSpace = (accessFlags & PDP11.ACCESS.VIRT)? 0 : this.addrDSpace;
/*
@ -1692,12 +1729,12 @@ CPUStatePDP11.prototype.getAddrByMode = function(mode, reg, accessFlags)
* Mode 2: (R)+
*/
case 2:
stepSize = 2;
step = 2;
virtualAddress = this.regsGen[reg];
if (reg != 7) {
virtualAddress |= addrDSpace;
if (reg < 6 && (accessFlags & PDP11.ACCESS.BYTE)) {
stepSize = 1;
step = 1;
}
}
this.nStepCycles -= (2 + 1);
@ -1707,7 +1744,7 @@ CPUStatePDP11.prototype.getAddrByMode = function(mode, reg, accessFlags)
* Mode 3: @(R)+
*/
case 3:
stepSize = 2;
step = 2;
virtualAddress = this.regsGen[reg];
if (reg != 7) virtualAddress |= addrDSpace;
virtualAddress = this.readWord(virtualAddress);
@ -1719,9 +1756,9 @@ CPUStatePDP11.prototype.getAddrByMode = function(mode, reg, accessFlags)
* Mode 4: -(R)
*/
case 4:
stepSize = -2;
if (reg < 6 && (accessFlags & PDP11.ACCESS.BYTE)) stepSize = -1;
virtualAddress = (this.regsGen[reg] + stepSize) & 0xffff;
step = -2;
if (reg < 6 && (accessFlags & PDP11.ACCESS.BYTE)) step = -1;
virtualAddress = (this.regsGen[reg] + step) & 0xffff;
if (reg != 7) virtualAddress |= addrDSpace;
this.nStepCycles -= (3 + 1);
break;
@ -1730,7 +1767,7 @@ CPUStatePDP11.prototype.getAddrByMode = function(mode, reg, accessFlags)
* Mode 5: @-(R)
*/
case 5:
stepSize = -2;
step = -2;
virtualAddress = (this.regsGen[reg] - 2) & 0xffff;
if (reg != 7) virtualAddress |= addrDSpace;
virtualAddress = this.readWord(virtualAddress) | addrDSpace;
@ -1757,17 +1794,14 @@ CPUStatePDP11.prototype.getAddrByMode = function(mode, reg, accessFlags)
return virtualAddress;
}
this.regsGen[reg] = (this.regsGen[reg] + stepSize) & 0xffff;
if (addrDSpace && !(this.regMMR0 & 0xe000)) {
this.regMMR1 = (this.regMMR1 << 8) | ((stepSize << 3) & 0xf8) | reg;
}
this.regsGen[reg] = (this.regsGen[reg] + step) & 0xffff;
this.lastAI = (this.lastAI << 8) | ((step << 3) & 0xf8) | reg;
/*
* NOTE: We had to eliminate the test for "(accessFlags & PDP11.ACCESS.WRITE)", because DEC's
* "TRAP TEST" expects "TST -(SP)" to trap when SP is 150.
*/
if (reg == 6 && stepSize < 0) {
if (reg == 6 && step < 0) {
this.checkStackLimit(mode, this.regsGen[6]);
}
return virtualAddress;
@ -1955,14 +1989,14 @@ CPUStatePDP11.prototype.writeWordToVirtual = function(virtualAddress, data)
*/
CPUStatePDP11.prototype.readWordFromPrevSpace = function(opCode, accessFlags)
{
var src;
var data;
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];
data = this.regsGen[reg];
} else {
src = this.regsAltStack[(this.regPSW >> 12) & 3];
data = this.regsAltStack[(this.regPSW >> 12) & 3];
}
} else {
var addr = this.getAddrByMode(mode, reg, PDP11.ACCESS.READ_WORD);
@ -1970,10 +2004,10 @@ CPUStatePDP11.prototype.readWordFromPrevSpace = function(opCode, accessFlags)
if ((this.regPSW & 0xf000) !== 0xf000) addr &= 0xffff;
}
this.mmuMode = (this.regPSW >> 12) & 3;
src = this.readWord(addr | (accessFlags & this.addrDSpace));
data = this.readWord(addr | (accessFlags & this.addrDSpace));
this.mmuMode = (this.regPSW >> 14) & 3;
}
return src;
return data;
};
/**
@ -1986,9 +2020,7 @@ CPUStatePDP11.prototype.readWordFromPrevSpace = function(opCode, accessFlags)
*/
CPUStatePDP11.prototype.writeWordToPrevSpace = function(opCode, accessFlags, data)
{
if (!(this.regMMR0 & 0xe000)) {
this.regMMR1 = 0x16;
}
this.lastAI = 0x0016;
var reg = this.dstReg = opCode & PDP11.OPREG.MASK;
var mode = this.dstMode = (opCode & PDP11.OPMODE.MASK) >> PDP11.OPMODE.SHIFT;
if (!mode) {
@ -2016,6 +2048,11 @@ CPUStatePDP11.prototype.writeWordToPrevSpace = function(opCode, accessFlags, dat
/**
* readSrcByte(opCode)
*
* WARNING: If the SRC operand is a register, we return a negative register number rather than the
* register value, because the final value of the register must be resolved AFTER the DST operand has
* been decoded and any pre-decrement or post-increment operations have been performed. See readSrcWord()
* for more details.
*
* @this {CPUStatePDP11}
* @param {number} opCode
* @return {number}
@ -2027,7 +2064,7 @@ CPUStatePDP11.prototype.readSrcByte = function(opCode)
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;
result = -reg-1;
} else {
result = this.readByteFromPhysical(this.getAddr(mode, reg, PDP11.ACCESS.READ_BYTE));
}
@ -2037,6 +2074,26 @@ CPUStatePDP11.prototype.readSrcByte = function(opCode)
/**
* readSrcWord(opCode)
*
* WARNING: If the SRC operand is a register, we return a negative register number rather than the
* register value, because the final value of the register must be resolved AFTER the DST operand has
* been decoded and any pre-decrement or post-increment operations have been performed.
*
* Here's an example from DEC's "TRAP TEST":
*
* 007200: 012700 006340 MOV #6340,R0
* 007204: 010020 MOV R0,(R0)+
* 007206: 026727 177126 006342 CMP 006340,#6342
* 007214: 001401 BEQ 007220
* 007216: 000000 HALT
*
* If we returned the value of R0 immediately, then "MOV R0,(R0)+" would write 6340 to the memory location,
* rather than 6342.
*
* Most callers don't need to worry about this, because if they pass the result from readSrcWord() directly
* to writeDstWord() or updateDstWord(), those functions will take care of converting any negative register
* number back into the proper register value. The exceptions are opcodes that don't modify the DST operand
* (BIT, BITB, CMP, and CMPB); those opcode handlers must deal with negative register numbers themselves.
*
* @this {CPUStatePDP11}
* @param {number} opCode
* @return {number}
@ -2048,7 +2105,7 @@ CPUStatePDP11.prototype.readSrcWord = function(opCode)
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];
result = -reg-1;
} else {
result = this.bus.getWord(this.getAddr(mode, reg, PDP11.ACCESS.READ_WORD));
}
@ -2110,46 +2167,55 @@ CPUStatePDP11.prototype.readDstWord = function(opCode)
};
/**
* updateDstByte(opCode, src, fnOp)
* updateDstByte(opCode, data, 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 {number} data
* @param {function(number,number)} fnOp
*/
CPUStatePDP11.prototype.updateDstByte = function(opCode, src, fnOp)
CPUStatePDP11.prototype.updateDstByte = function(opCode, data, fnOp)
{
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] & 0xff);
var dst = this.regsGen[reg];
data = (data < 0? (this.regsGen[-data-1] & 0xff) : data);
this.regsGen[reg] = (dst & 0xff00) | fnOp.call(this, data, dst & 0xff);
} else {
var addr = this.dstAddr = this.getAddr(mode, reg, PDP11.ACCESS.UPDATE_BYTE);
this.writeByteToPhysical(addr, fnOp.call(this, src, this.readByteFromPhysical(addr)));
data = (data < 0? (this.regsGen[-data-1] & 0xff) : data);
this.writeByteToPhysical(addr, fnOp.call(this, data, this.readByteFromPhysical(addr)));
}
};
/**
* updateDstWord(opCode, src, fnOp)
* updateDstWord(opCode, data, 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 {number} data
* @param {function(number,number)} fnOp
*/
CPUStatePDP11.prototype.updateDstWord = function(opCode, src, fnOp)
CPUStatePDP11.prototype.updateDstWord = function(opCode, data, fnOp)
{
var reg = this.dstReg = opCode & PDP11.OPREG.MASK;
var mode = this.dstMode = (opCode & PDP11.OPMODE.MASK) >> PDP11.OPMODE.SHIFT;
/*
* TODO: If callers are careful about masking data, then we don't need to mask it here or in bus.setWord().
*/
this.assert(data < 0 && data >= -8 || !(data & ~0xffff));
if (!mode) {
this.regsGen[reg] = fnOp.call(this, src, this.regsGen[reg]);
this.regsGen[reg] = fnOp.call(this, data < 0? this.regsGen[-data-1] : data, this.regsGen[reg]);
} else {
var addr = this.getAddr(mode, reg, PDP11.ACCESS.UPDATE_WORD);
this.bus.setWord(addr, fnOp.call(this, src, this.bus.getWord(addr)));
this.bus.setWord(addr, fnOp.call(this, data < 0? this.regsGen[-data-1] : data, this.bus.getWord(addr)));
}
};
@ -2180,10 +2246,12 @@ CPUStatePDP11.prototype.writeDstByte = function(opCode, data, writeFlags)
* Potentially worthwhile optimization: skipping the sign-extending data shifts
* if writeFlags is WRITE.BYTE (but that requires an extra test and separate code paths).
*/
data = (data < 0? (this.regsGen[-data-1] & 0xff): data);
this.regsGen[reg] = (this.regsGen[reg] & ~writeFlags) | (((data << 24) >> 24) & writeFlags);
}
} else {
this.writeByteToPhysical(this.getAddr(mode, reg, PDP11.ACCESS.WRITE_BYTE), data);
var addr = this.getAddr(mode, reg, PDP11.ACCESS.WRITE_BYTE);
this.writeByteToPhysical(addr, (data = data < 0? (this.regsGen[-data-1] & 0xff): data));
}
return data;
};
@ -2202,10 +2270,17 @@ 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;
/*
* TODO: If callers are careful about masking data, then we don't need to mask it here or in bus.setWord().
*/
this.assert(data < 0 && data >= -8 || !(data & ~0xffff));
if (!mode) {
this.regsGen[reg] = data & 0xffff;
this.regsGen[reg] = data < 0? this.regsGen[-data-1] : (data & 0xffff);
} else {
this.bus.setWord(this.getAddr(mode, reg, PDP11.ACCESS.WRITE_WORD), data);
var addr = this.getAddr(mode, reg, PDP11.ACCESS.WRITE_WORD);
this.bus.setWord(addr, data < 0? this.regsGen[-data-1] : data);
}
return data;
};
@ -2304,7 +2379,7 @@ CPUStatePDP11.prototype.stepCPU = function(nMinCycles)
* an interrupt can trigger a TRAP_SP stack overflow condition, which must be dealt with BEFORE we
* execute the first instruction of the interrupt handler.
*/
if ((this.opFlags & (PDP11.OPFLAG.INTQ_SPL | PDP11.OPFLAG.INTQ | PDP11.OPFLAG.WAIT)) /* && nDebugState >= 0 */) {
if ((this.opFlags & (PDP11.OPFLAG.INTQ_MASK | PDP11.OPFLAG.WAIT)) /* && nDebugState >= 0 */) {
if (this.checkInterrupts()) {
/*
* Since an interrupt was just dispatched, altering the normal flow of time and changing

View file

@ -431,7 +431,7 @@ if (DEBUGGER) {
DebuggerPDP11.OPNONE = [DebuggerPDP11.OPS.NONE];
/*
* Table of opcodes that are specific to the 11/45 and higher
* Table of opcodes specific to the 11/45 and newer
*/
DebuggerPDP11.OP1145 = [
DebuggerPDP11.OPS.MARK,

View file

@ -161,19 +161,19 @@ var PDP11 = {
* Processor Status flag definitions (stored in regPSW)
*/
PSW: {
CF: 0x0001, // bit 0: Carry Flag
VF: 0x0002, // bit 1: Overflow Flag (aka OF on Intel processors)
ZF: 0x0004, // bit 2: Zero Flag
NF: 0x0008, // bit 3: Negative Flag (aka SF -- Sign Flag -- on Intel processors)
TF: 0x0010, // bit 4: Trap Flag
PRI: 0x00E0, // bits 5-7: Priority
UNUSED: 0x0700, // bits 8-10: unused
CF: 0x0001, // bit 0 (000001) Carry Flag
VF: 0x0002, // bit 1 (000002) Overflow Flag (aka OF on Intel processors)
ZF: 0x0004, // bit 2 (000004) Zero Flag
NF: 0x0008, // bit 3 (000010) Negative Flag (aka SF -- Sign Flag -- on Intel processors)
TF: 0x0010, // bit 4 (000020) Trap Flag
PRI: 0x00E0, // bits 5-7 (000340) Priority
UNUSED: 0x0700, // bits 8-10 (003400) UNUSED
/*
* PSW bits above this point are unused on 11/20-class machines
*/
REGSET: 0x0800, // bit 11: Register Set (
PMODE: 0x3000, // bits 12-13: Prev Mode (see PDP11.MODE)
CMODE: 0xC000, // bits 14-15: Curr Mode (see PDP11.MODE)
REGSET: 0x0800, // bit 11 (004000) Register Set
PMODE: 0x3000, // bits 12-13 (030000) Prev Mode (see PDP11.MODE)
CMODE: 0xC000, // bits 14-15 (140000) Curr Mode (see PDP11.MODE)
SHIFT: {
CF: 0,
VF: 1,
@ -197,8 +197,9 @@ var PDP11 = {
* Internal operation state flags
*/
OPFLAG: {
INTQ_SPL: 0x01, // INTQ triggered by SPL
INTQ_CHK: 0x01, // set INTQ on next check (set by SPL and assorted traps)
INTQ: 0x02, // call checkInterrupts()
INTQ_MASK: 0x03,
WAIT: 0x04, // WAIT operation in progress
TRAP: 0x08, // set if last operation was a trap (see trapLast for the vector, and trapReason for the reason)
TRAP_TF: 0x10, // aka PDP11.PSW.TF

View file

@ -243,19 +243,7 @@ DevicePDP11.prototype.readMMR1 = function(addr)
*/
DevicePDP11.prototype.readMMR2 = function(addr)
{
return this.cpu.regMMR2;
};
/**
* writeMMR2(data, addr)
*
* @this {DevicePDP11}
* @param {number} data
* @param {number} addr (eg, PDP11.UNIBUS.MMR2 or 177576)
*/
DevicePDP11.prototype.writeMMR2 = function(data, addr)
{
this.cpu.regMMR2 = data;
return this.cpu.getMMR2();
};
/**

View file

@ -287,6 +287,7 @@ PC11.prototype.initBus = function(cmp, bus, cpu, dbg)
});
bus.addIOTable(this, PC11.UNIBUS_IOTABLE);
bus.addResetHandler(this.reset.bind(this));
this.addTape("None", PC11.SOURCE.NONE, true);
if (this.fLocalTapes) this.addTape("Local Tape", PC11.SOURCE.LOCAL);

View file

@ -283,6 +283,7 @@ RL11.prototype.initBus = function(cmp, bus, cpu, dbg)
this.triggerInterrupt = this.cpu.addTrigger(PDP11.RL11.VEC, PDP11.RL11.PRI);
bus.addIOTable(this, RL11.UNIBUS_IOTABLE, MessagesPDP11.DISK);
bus.addResetHandler(this.reset.bind(this));
this.addDisk("None", RL11.SOURCE.NONE, true);
if (this.fLocalDisks) this.addDisk("Local Disk", RL11.SOURCE.LOCAL);

View file

@ -312,6 +312,8 @@ SerialPortPDP11.prototype.initBus = function(cmp, bus, cpu, dbg)
});
bus.addIOTable(this, SerialPortPDP11.UNIBUS_IOTABLE);
bus.addResetHandler(this.reset.bind(this));
this.setReady();
};
@ -460,7 +462,7 @@ SerialPortPDP11.prototype.initState = function(data)
this.rbuf = 0;
this.rcsr = 0;
this.xcsr = PDP11.DL11.XCSR.READY;
this.abReceive = [];
// this.abReceive = [];
return true;
};