Fixed bug in writeDstWord() that was updating flags with negative data (and sadly, none of DEC's basic tests caught it)
This commit is contained in:
parent
91bd3c1a7a
commit
17816f6fcc
8 changed files with 404 additions and 381 deletions
|
|
@ -1398,7 +1398,7 @@ BusPDP11.prototype.fault = function(addr, err, access)
|
|||
this.dbg.printMessage("memory fault (" + access + ") on " + this.dbg.toStrBase(addr), true, true);
|
||||
}
|
||||
if (err) this.cpu.regErr |= err;
|
||||
this.cpu.trap(PDP11.TRAP.BUS_ERROR, 0, addr);
|
||||
this.cpu.trap(PDP11.TRAP.BUS, 0, addr);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -831,7 +831,7 @@ PDP11.opBPL = function(opCode)
|
|||
*/
|
||||
PDP11.opBPT = function(opCode)
|
||||
{
|
||||
this.trap(PDP11.TRAP.BPT, 0, PDP11.REASON.TRAP);
|
||||
this.trap(PDP11.TRAP.BPT, 0, PDP11.REASON.OPCODE);
|
||||
this.nStepCycles -= (4 + 1);
|
||||
};
|
||||
|
||||
|
|
@ -1105,7 +1105,7 @@ PDP11.opDIV = function(opCode)
|
|||
*/
|
||||
PDP11.opEMT = function(opCode)
|
||||
{
|
||||
this.trap(PDP11.TRAP.EMT, 0, PDP11.REASON.TRAP);
|
||||
this.trap(PDP11.TRAP.EMT, 0, PDP11.REASON.OPCODE);
|
||||
this.nStepCycles -= (22 + 3);
|
||||
};
|
||||
|
||||
|
|
@ -1119,7 +1119,7 @@ PDP11.opHALT = function(opCode)
|
|||
{
|
||||
if (this.regPSW & PDP11.PSW.CMODE) {
|
||||
this.regErr |= PDP11.CPUERR.BADHALT;
|
||||
this.trap(PDP11.TRAP.BUS_ERROR, 0, PDP11.REASON.HALT);
|
||||
this.trap(PDP11.TRAP.BUS, 0, PDP11.REASON.HALT);
|
||||
} else {
|
||||
if (this.panel) {
|
||||
this.panel.setData(this.regsGen[0], true);
|
||||
|
|
@ -1178,7 +1178,7 @@ PDP11.opINCB = function(opCode)
|
|||
*/
|
||||
PDP11.opIOT = function(opCode)
|
||||
{
|
||||
this.trap(PDP11.TRAP.IOT, 0, PDP11.REASON.TRAP);
|
||||
this.trap(PDP11.TRAP.IOT, 0, PDP11.REASON.OPCODE);
|
||||
this.nStepCycles -= (22 + 3);
|
||||
};
|
||||
|
||||
|
|
@ -1298,7 +1298,7 @@ PDP11.opMFPT = function(opCode)
|
|||
/*
|
||||
* TODO: Review
|
||||
*/
|
||||
this.trap(PDP11.TRAP.RESERVED, 0, PDP11.REASON.TRAP);
|
||||
this.trap(PDP11.TRAP.RESERVED, 0, PDP11.REASON.OPCODE);
|
||||
};
|
||||
|
||||
PDP11.MOV_CYCLES = [
|
||||
|
|
@ -1671,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_CHK;
|
||||
this.opFlags |= PDP11.OPFLAG.INTQ_DELAY;
|
||||
}
|
||||
this.nStepCycles -= (4 + 1);
|
||||
};
|
||||
|
|
@ -1720,7 +1720,7 @@ PDP11.opSXT = function(opCode)
|
|||
*/
|
||||
PDP11.opTRAP = function(opCode)
|
||||
{
|
||||
this.trap(PDP11.TRAP.TRAP, 0, PDP11.REASON.TRAP);
|
||||
this.trap(PDP11.TRAP.TRAP, 0, PDP11.REASON.OPCODE);
|
||||
this.nStepCycles -= (4 + 1);
|
||||
};
|
||||
|
||||
|
|
@ -1830,7 +1830,7 @@ PDP11.opUndefined = function(opCode)
|
|||
if (DEBUGGER && this.dbg) {
|
||||
if (this.dbg.undefinedInstruction(opCode)) return;
|
||||
}
|
||||
this.trap(PDP11.TRAP.RESERVED, 0, PDP11.REASON.TRAP);
|
||||
this.trap(PDP11.TRAP.RESERVED, 0, PDP11.REASON.OPCODE);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -590,9 +590,9 @@ CPUStatePDP11.prototype.getOpcode = function()
|
|||
this.lastAI = 0;
|
||||
this.lastPC = pc;
|
||||
/*
|
||||
* If PC is misaligned, a BUS_ERROR trap will be generated, and because it will generate an
|
||||
* If PC is unaligned, a BUS 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().
|
||||
* original unaligned PC will be pushed onto the stack by trap().
|
||||
*/
|
||||
var op = this.readWord(pc);
|
||||
this.regsGen[PDP11.REG.PC] = (pc + 2) & 0xffff;
|
||||
|
|
@ -819,10 +819,10 @@ CPUStatePDP11.prototype.checkInterrupts = function()
|
|||
fInterrupt = true;
|
||||
}
|
||||
}
|
||||
else if (this.opFlags & PDP11.OPFLAG.INTQ_CHK) {
|
||||
else if (this.opFlags & PDP11.OPFLAG.INTQ_DELAY) {
|
||||
/*
|
||||
* 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.
|
||||
* We know that INTQ (bit 1) is clear, so since INTQ_DELAY (bit 0) is set, incrementing opFlags
|
||||
* will transform INTQ_DELAY into INTQ, without affecting any other (higher) bits.
|
||||
*/
|
||||
this.opFlags++;
|
||||
}
|
||||
|
|
@ -899,11 +899,11 @@ CPUStatePDP11.prototype.dispatchInterrupt = function(vector, priority)
|
|||
CPUStatePDP11.prototype.checkTraps = function()
|
||||
{
|
||||
if (this.opFlags & PDP11.OPFLAG.TRAP_MMU) {
|
||||
this.trap(PDP11.TRAP.MMU, PDP11.OPFLAG.TRAP_MMU, PDP11.REASON.TRAP);
|
||||
this.trap(PDP11.TRAP.MMU, PDP11.OPFLAG.TRAP_MMU, PDP11.REASON.FAULT);
|
||||
return true;
|
||||
}
|
||||
if (this.opFlags & PDP11.OPFLAG.TRAP_SP) {
|
||||
this.trap(PDP11.TRAP.BUS_ERROR, PDP11.OPFLAG.TRAP_SP, PDP11.REASON.STACK);
|
||||
this.trap(PDP11.TRAP.BUS, PDP11.OPFLAG.TRAP_SP, PDP11.REASON.YELLOW);
|
||||
return true;
|
||||
}
|
||||
if (this.opFlags & PDP11.OPFLAG.TRAP_TF) {
|
||||
|
|
@ -1263,6 +1263,7 @@ CPUStatePDP11.prototype.trap = function(vector, flag, reason)
|
|||
*/
|
||||
this.regErr |= PDP11.CPUERR.RED;
|
||||
this.regsGen[6] = 4;
|
||||
reason = PDP11.REASON.RED;
|
||||
}
|
||||
|
||||
this.lastPC = vector;
|
||||
|
|
@ -1310,22 +1311,22 @@ CPUStatePDP11.prototype.trap = function(vector, flag, reason)
|
|||
*
|
||||
* 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
|
||||
* trick that the SPL instruction uses: setting INTQ_DELAY 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 | PDP11.OPFLAG.TRAP_TF | PDP11.OPFLAG.INTQ);
|
||||
this.opFlags |= PDP11.OPFLAG.INTQ_CHK;
|
||||
this.opFlags |= PDP11.OPFLAG.INTQ_DELAY | PDP11.OPFLAG.TRAP;
|
||||
|
||||
this.trapPSW = -1; // reset flag that we have a trap within a trap
|
||||
|
||||
/*
|
||||
* These next properties are purely an aid for the Debugger; see getTrapStatus()
|
||||
* These next properties (in conjunction with setting PDP11.OPFLAG.TRAP) are purely an aid for the Debugger;
|
||||
* see getTrapStatus().
|
||||
*/
|
||||
this.opFlags |= PDP11.OPFLAG.TRAP;
|
||||
this.trapVector = vector;
|
||||
this.trapReason = reason;
|
||||
|
||||
if (reason != PDP11.REASON.INTERRUPT) throw vector;
|
||||
if (reason >= PDP11.REASON.RED) throw vector;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -1491,72 +1492,77 @@ CPUStatePDP11.prototype.mapVirtualToPhysical = function(virtualAddress, accessFl
|
|||
var errorMask = 0;
|
||||
switch (pdr & 0x7) {
|
||||
case 1: // read-only with trap
|
||||
errorMask = 0x1000; // MMU trap
|
||||
errorMask = PDP11.MMR0.TRAP_MMU;
|
||||
/* falls through */
|
||||
case 2: // read-only
|
||||
pdr |= 0x80; // Set A bit
|
||||
if (accessFlags & PDP11.ACCESS.WRITE) {
|
||||
errorMask = 0x2000; // read-only abort
|
||||
errorMask = PDP11.MMR0.ABORT_RO;
|
||||
}
|
||||
break;
|
||||
case 4: // read-write with read-write trap
|
||||
errorMask = 0x1000; // MMU trap
|
||||
errorMask = PDP11.MMR0.TRAP_MMU;
|
||||
/* falls through */
|
||||
case 5: // read-write with write trap
|
||||
if (accessFlags & PDP11.ACCESS.WRITE) {
|
||||
errorMask = 0x1000; // MMU trap
|
||||
errorMask = PDP11.MMR0.TRAP_MMU;
|
||||
}
|
||||
/* falls through */
|
||||
case 6: // read-write: set A & W bits
|
||||
pdr |= ((accessFlags & PDP11.ACCESS.WRITE) ? 0xc0 : 0x80);
|
||||
break;
|
||||
default:
|
||||
errorMask = 0x8000; // non-resident abort
|
||||
errorMask = PDP11.MMR0.ABORT_NR;
|
||||
break;
|
||||
}
|
||||
|
||||
if ((pdr & 0x7f08) !== 0x7f00) { // skip checking most common case (hopefully)
|
||||
if ((pdr & 0x7f08) != 0x7f00) { // skip checking most common case (hopefully)
|
||||
if (pdr & 0x8) { // expand downwards
|
||||
if (pdr & 0x7f00) {
|
||||
if ((virtualAddress & 0x1fc0) < ((pdr >> 2) & 0x1fc0)) {
|
||||
errorMask |= 0x4000; // page length error abort
|
||||
errorMask |= PDP11.MMR0.ABORT_PL;
|
||||
}
|
||||
}
|
||||
} else { // expand upwards
|
||||
if ((virtualAddress & 0x1fc0) > ((pdr >> 2) & 0x1fc0)) {
|
||||
errorMask |= 0x4000; // page length error abort
|
||||
errorMask |= PDP11.MMR0.ABORT_PL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// aborts and traps: log FIRST trap and MOST RECENT abort
|
||||
/*
|
||||
* Aborts and traps: log FIRST trap and MOST RECENT abort
|
||||
*/
|
||||
|
||||
this.mmuPDR[this.mmuMode][page] = pdr;
|
||||
if ((physicalAddress !== 0x3fff7a) || this.mmuMode) {// MMR0 is 017777572
|
||||
if (physicalAddress != ((BusPDP11.IOPAGE_22BIT | PDP11.UNIBUS.MMR0) & this.mmuMask) || this.mmuMode) {
|
||||
this.mmuLastMode = this.mmuMode;
|
||||
this.mmuLastPage = page;
|
||||
}
|
||||
|
||||
var fTrap = false;
|
||||
var fAbort = false;
|
||||
if (errorMask) {
|
||||
if (errorMask & 0xe000) {
|
||||
if (errorMask & PDP11.MMR0.ABORT) {
|
||||
if (this.trapPSW >= 0) errorMask |= 0x80; // Instruction complete
|
||||
if (!(this.regMMR0 & 0xe000)) {
|
||||
if (!(this.regMMR0 & PDP11.MMR0.ABORT)) {
|
||||
this.regMMR0 |= errorMask | (this.mmuLastMode << 5) | (this.mmuLastPage << 1);
|
||||
}
|
||||
fTrap = true;
|
||||
fAbort = true;
|
||||
}
|
||||
if (!(this.regMMR0 & 0xf000)) {
|
||||
//if (physicalAddress < 017772200 || physicalAddress > 017777677) {
|
||||
if (physicalAddress < 0x3ff480 || physicalAddress > 0x3fffbf) {
|
||||
this.regMMR0 |= 0x1000; // MMU trap flag
|
||||
if (this.regMMR0 & 0x0200) {
|
||||
if (!(this.regMMR0 & (PDP11.MMR0.ABORT | PDP11.MMR0.TRAP_MMU))) {
|
||||
/*
|
||||
* TODO: Review the code below, because the address range seems over-inclusive.
|
||||
*/
|
||||
if (physicalAddress < ((BusPDP11.IOPAGE_22BIT | PDP11.UNIBUS.SIPDR0) & this.mmuMask) ||
|
||||
physicalAddress > ((BusPDP11.IOPAGE_22BIT | PDP11.UNIBUS.UDPAR7 | 0x1) & this.mmuMask)) {
|
||||
this.regMMR0 |= PDP11.MMR0.TRAP_MMU;
|
||||
if (this.regMMR0 & PDP11.MMR0.MMU_TRAPS) {
|
||||
this.opFlags |= PDP11.OPFLAG.TRAP_MMU;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (fTrap) { // don't trap until the end, because it throws an exception
|
||||
this.trap(PDP11.TRAP.MMU, 0, PDP11.REASON.ERROR);
|
||||
if (fAbort) { // don't abort until the end, because it throws an exception
|
||||
this.trap(PDP11.TRAP.MMU, 0, PDP11.REASON.ABORT);
|
||||
}
|
||||
}
|
||||
return physicalAddress;
|
||||
|
|
@ -1641,7 +1647,7 @@ CPUStatePDP11.prototype.checkStackLimit = function(mode, addr)
|
|||
if (this.model >= PDP11.MODEL_1145 && (addr <= this.regSL - 32 /* || mode == 1 && addr >= 0xFFFE */)) {
|
||||
this.regErr |= PDP11.CPUERR.RED;
|
||||
this.regsGen[6] = 4;
|
||||
this.trap(PDP11.TRAP.BUS_ERROR, 0, PDP11.REASON.STACK);
|
||||
this.trap(PDP11.TRAP.BUS, 0, PDP11.REASON.RED);
|
||||
} else {
|
||||
/*
|
||||
* On older machines (eg, the PDP-11/20), the instruction is always allowed to complete,
|
||||
|
|
@ -1708,11 +1714,11 @@ CPUStatePDP11.prototype.getAddrByMode = function(mode, reg, accessFlags)
|
|||
*
|
||||
* NOTE: Most instruction code paths never call getAddrByMode() when the mode is zero;
|
||||
* JMP and JSR instructions are exceptions, but that's OK, because those are documented as
|
||||
* ILLEGAL instructions which produce a BUS_ERROR trap (as opposed to UNDEFINED instructions
|
||||
* ILLEGAL instructions which produce a BUS trap (as opposed to UNDEFINED instructions
|
||||
* that cause a RESERVED trap).
|
||||
*/
|
||||
case 0:
|
||||
this.trap(PDP11.TRAP.BUS_ERROR, 0, PDP11.REASON.ILLEGAL);
|
||||
this.trap(PDP11.TRAP.BUS, 0, PDP11.REASON.ILLEGAL);
|
||||
return 0;
|
||||
|
||||
/*
|
||||
|
|
@ -2208,6 +2214,7 @@ CPUStatePDP11.prototype.updateDstWord = function(opCode, data, fnOp)
|
|||
|
||||
/*
|
||||
* TODO: If callers are careful about masking data, then we don't need to mask it here or in bus.setWord().
|
||||
* We've eliminated the 0xffff data mask here, but bus.setWord() is still masking.
|
||||
*/
|
||||
this.assert(data < 0 && data >= -8 || !(data & ~0xffff));
|
||||
|
||||
|
|
@ -2273,14 +2280,15 @@ CPUStatePDP11.prototype.writeDstWord = function(opCode, data)
|
|||
|
||||
/*
|
||||
* TODO: If callers are careful about masking data, then we don't need to mask it here or in bus.setWord().
|
||||
* We've eliminated the 0xffff data mask here, but bus.setWord() is still masking.
|
||||
*/
|
||||
this.assert(data < 0 && data >= -8 || !(data & ~0xffff));
|
||||
|
||||
if (!mode) {
|
||||
this.regsGen[reg] = data < 0? this.regsGen[-data-1] : (data & 0xffff);
|
||||
this.regsGen[reg] = (data = (data < 0? this.regsGen[-data-1] : data));
|
||||
} else {
|
||||
var addr = this.getAddr(mode, reg, PDP11.ACCESS.WRITE_WORD);
|
||||
this.bus.setWord(addr, data < 0? this.regsGen[-data-1] : data);
|
||||
this.bus.setWord(addr, (data = (data < 0? this.regsGen[-data-1] : data)));
|
||||
}
|
||||
return data;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1220,7 +1220,7 @@ if (DEBUGGER) {
|
|||
if (this.sMessagePrev && sMessage == this.sMessagePrev) return;
|
||||
this.sMessagePrev = sMessage;
|
||||
|
||||
if ((this.bitsMessage & MessagesPDP11.HALT) && this.cpu && this.cpu.isRunning()) {
|
||||
if ((this.bitsMessage & MessagesPDP11.HALT) && this.cpu && this.cpu.isRunning() || this.isBusy(true)) {
|
||||
this.stopCPU();
|
||||
sMessage += " (cpu halted)";
|
||||
}
|
||||
|
|
@ -2984,10 +2984,10 @@ if (DEBUGGER) {
|
|||
*
|
||||
* Besides, it's nice for "db" and "dw" to generate the same Bus activity that typical byte and word reads do.
|
||||
*/
|
||||
var i, n;
|
||||
var i = nBytesPerLine;
|
||||
var data = 0, shift = 0;
|
||||
for (i = nBytesPerLine; i > 0 && nBytes > 0; i -= n, nBytes -= n) {
|
||||
n = 1;
|
||||
while (i > 0 && nBytes > 0) {
|
||||
var n = 1;
|
||||
var v = size == 1? this.getByte(dbgAddr, n) : this.getWord(dbgAddr, (n = 2));
|
||||
data |= (v << (shift << 3));
|
||||
shift += n;
|
||||
|
|
@ -3001,7 +3001,12 @@ if (DEBUGGER) {
|
|||
}
|
||||
data = shift = 0;
|
||||
}
|
||||
sChars += (v >= 32 && v < 128? String.fromCharCode(v) : '.');
|
||||
i -= n; nBytes -= n;
|
||||
while (n--) {
|
||||
var c = v & 0xff;
|
||||
sChars += (c >= 32 && c < 128? String.fromCharCode(c) : '.');
|
||||
v >>= 8;
|
||||
}
|
||||
}
|
||||
if (sDump) sDump += "\n";
|
||||
if (fJSON) {
|
||||
|
|
|
|||
|
|
@ -82,7 +82,7 @@ var TYPEDARRAYS = (typeof ArrayBuffer !== 'undefined');
|
|||
* MEMFAULT forces the Memory interfaces to signal a CPU fault when a word is accessed using an odd (unaligned) address.
|
||||
*
|
||||
* Since PDPjs inherited its Bus component from PCx86, it included support for both aligned and unaligned word accesses
|
||||
* by default. However, the PDP-11 adds a wrinkle: when an odd address is used to access a memory word, a BUS_ERROR trap
|
||||
* by default. However, the PDP-11 adds a wrinkle: when an odd address is used to access a memory word, a BUS trap
|
||||
* must be generated. Note that odd IOPAGE word accesses are fine; this only affects the Memory component.
|
||||
*
|
||||
* When the MMU is enabled, these checks may also be performed at a higher level, eliminating the need for them at the
|
||||
|
|
@ -197,13 +197,13 @@ var PDP11 = {
|
|||
* Internal operation state flags
|
||||
*/
|
||||
OPFLAG: {
|
||||
INTQ_CHK: 0x01, // set INTQ on next check (set by SPL and assorted traps)
|
||||
INTQ_DELAY: 0x01, // set INTQ on next check (set by SPL and 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
|
||||
TRAP_SP: 0x20, // set for a deferred BUS_ERROR trap (due to a "yellow" stack overflow condition)
|
||||
TRAP_SP: 0x20, // set for a deferred BUS trap (due to a "yellow" stack overflow condition)
|
||||
TRAP_MMU: 0x40,
|
||||
TRAP_MASK: 0x70,
|
||||
NO_FLAGS: 0x80, // set whenever the PSW is written directly, requiring all updateXXXFlags() functions to leave flags unchanged
|
||||
|
|
@ -251,7 +251,7 @@ var PDP11 = {
|
|||
*/
|
||||
TRAP: {
|
||||
UNDEFINED: 0x00, // 000 (reserved)
|
||||
BUS_ERROR: 0x04, // 004 illegal instruction, unaligned address, invalid memory, stack limit, microbreak
|
||||
BUS: 0x04, // 004 unaligned address, non-existent memory, illegal instruction, etc
|
||||
RESERVED: 0x08, // 010 reserved instructions
|
||||
BPT: 0x0C, // 014 BPT: breakpoint trap (trace)
|
||||
IOT: 0x10, // 020 IOT: input/output trap
|
||||
|
|
@ -262,27 +262,31 @@ var PDP11 = {
|
|||
MMU: 0xA8 // 250 MMU: aborts and traps
|
||||
},
|
||||
/*
|
||||
* PDP-11 trap reasons (largely for diagnostic purposes only)
|
||||
* PDP-11 trap reasons; the reason may also be a non-negative address indicating a BUS memory error
|
||||
* (unaligned address or non-existent memory). Any reason >= RED (which includes BUS memory errors) generate
|
||||
* immediate (thrown) traps; the rest generate synchronous traps.
|
||||
*/
|
||||
REASON: {
|
||||
UNKNOWN: 0,
|
||||
TRAP: -1,
|
||||
HALT: -2,
|
||||
INTERRUPT: -3,
|
||||
TRACE: -4,
|
||||
STACK: -5,
|
||||
ILLEGAL: -6,
|
||||
ERROR: -7,
|
||||
ABORT: -1, // immediate MMU fault
|
||||
ILLEGAL: -2, // immediate invalid opcode (BUS)
|
||||
RED: -3, // immediate stack overflow fault (BUS)
|
||||
YELLOW: -4, // deferred stack overflow fault (BUS)
|
||||
FAULT: -5, // deferred MMU fault
|
||||
TRACE: -6, // deferred TF fault (BPT)
|
||||
HALT: -7, // illegal HALT (BUS)
|
||||
OPCODE: -8, // opcode-generated trap (eg, BPT, EMT, IOT, TRAP, or RESERVED opcode)
|
||||
INTERRUPT: -9, // device-generated trap (vector is device-specific)
|
||||
},
|
||||
REASONS: [
|
||||
"UNKNOWN",
|
||||
"TRAP",
|
||||
"HALT",
|
||||
"INTERRUPT",
|
||||
"TRACE",
|
||||
"STACK",
|
||||
"ABORT",
|
||||
"ILLEGAL",
|
||||
"ERROR"
|
||||
"RED",
|
||||
"YELLOW",
|
||||
"FAULT",
|
||||
"TRACE",
|
||||
"HALT",
|
||||
"OPCODE",
|
||||
"INTERRUPT"
|
||||
],
|
||||
/*
|
||||
* Internal memory access flags
|
||||
|
|
|
|||
|
|
@ -690,6 +690,11 @@ SerialPortPDP11.prototype.writeXBUF = function(data, addr)
|
|||
if (data) {
|
||||
this.transmitByte(data);
|
||||
this.xcsr &= ~PDP11.DL11.XCSR.READY;
|
||||
/*
|
||||
* NOTE: When debugging issues involving the SerialPort, such as debugging code between a pair of
|
||||
* transmitted bytes, you can pass 0 instead of getBaudTimeout() to setTimer() to minimize the amount
|
||||
* of time spent waiting for XCSR.READY to be set again.
|
||||
*/
|
||||
this.cpu.setTimer(this.timerTransmitInterrupt, this.getBaudTimeout(this.nBaudTransmit));
|
||||
}
|
||||
};
|
||||
|
|
|
|||
Loading…
Reference in a new issue