Fixed fault generation on invalid memory accesses; PDP-11 BASIC now starts up!

This commit is contained in:
Jeff Parsons 2016-10-21 17:06:41 -07:00 committed by Jeff Parsons
commit 5f05913036
9 changed files with 360 additions and 351 deletions

View file

@ -667,7 +667,7 @@ Memory.prototype = {
*/
readNone: function readNone(off, addr) {
if (DEBUGGER && this.dbg && this.dbg.messageEnabled(Messages.CPU | Messages.MEM) /* && !off */) {
this.dbg.message("attempt to read invalid block %" + str.toHex(this.addr), true);
this.dbg.message("attempt to read invalid block %" + str.toHex(addr), true);
}
return 0xff;
},
@ -681,7 +681,7 @@ Memory.prototype = {
*/
writeNone: function writeNone(off, v, addr) {
if (DEBUGGER && this.dbg && this.dbg.messageEnabled(Messages.CPU | Messages.MEM) /* && !off */) {
this.dbg.message("attempt to write " + str.toHexWord(v) + " to invalid block %" + str.toHex(this.addr), true);
this.dbg.message("attempt to write " + str.toHexWord(v) + " to invalid block %" + str.toHex(addr), true);
}
},
/**

View file

@ -556,7 +556,7 @@ BusPDP11.prototype.unknownAccess = function(addr, fByte, data)
* TODO: For 22-bit machines, let's display addr as a 3-byte value (for a total of 9 octal digits)
*/
this.dbg.printMessage("warning: unknown I/O access (" + this.dbg.toStrBase(addr) + "," + this.dbg.toStrBase(data, fByte?1:2) + ")", true, true);
if (this.dbg.stopInstruction()) return 0;
this.dbg.stopInstruction();
}
if (!this.nDisableFaults) {
this.cpu.trap(PDP11.TRAP.BUS_ERROR, addr);
@ -1255,18 +1255,20 @@ BusPDP11.prototype.addResetHandler = function(fnReset)
};
/**
* fault(addr)
* fault(addr, access)
*
* Memory interface for signaling alignment errors.
* Memory interface for signaling alignment errors, invalid memory
*
* @this {BusPDP11}
* @param {number} addr
* @param {number} [access] (for diagnostic purposes only)
*/
BusPDP11.prototype.fault = function(addr)
BusPDP11.prototype.fault = function(addr, access)
{
if (!this.nDisableFaults) {
if (DEBUGGER && this.dbg && this.dbg.messageEnabled(MessagesPDP11.WARN)) {
this.dbg.printMessage("memory fault on address " + this.dbg.toStrBase(addr), true, true);
if (DEBUGGER && this.dbg && this.dbg.messageEnabled(MessagesPDP11.BUS)) {
this.dbg.printMessage("memory fault (" + access + ") on address " + this.dbg.toStrBase(addr), true, true);
this.dbg.stopInstruction();
}
this.cpu.trap(PDP11.TRAP.BUS_ERROR, addr);
}

View file

@ -1664,7 +1664,12 @@ if (DEBUGGER) {
if (cpu.isRunning()) {
cpu.setPC(this.cpu.getLastPC());
this.stopCPU();
throw -1; // TODO: Review the appropriate-ness of throwing a bogus vector number in order to immediately stop the instruction
/*
* TODO: Review the appropriate-ness of throwing a bogus vector number in order to immediately stop
* the instruction. It's handy, but it also means that we no longer actually return true, so callers
* of either stopInstruction() or undefinedInstruction() may have unreachable code paths.
*/
throw -1;
}
return false;
};
@ -2091,8 +2096,8 @@ if (DEBUGGER) {
/*
* If getOperand() returns an Array rather than a string, then the first element is the original
* operand, and the second element contains an alternate representation of the operand (eg, target address,
* memory contents, etc).
* operand, and the second element contains an alternate representation of the operand (eg, target
* address, memory contents, etc).
*/
if (typeof sOperand != "string") {
sTarget = sOperand[1];
@ -2278,7 +2283,7 @@ if (DEBUGGER) {
/**
* parseInstruction(sOp, sOperand, addr)
*
* TODO: Unimplemented. See parseInstruction() in modules/c1pjs/lib/debugger.js for a working implementation.
* TODO: Unimplemented. See parseInstruction() in modules/c1pjs/lib/debugger.js for a sample implementation.
*
* @this {DebuggerPDP11}
* @param {string} sOp

View file

@ -248,7 +248,7 @@ var PDP11 = {
*/
TRAP: {
UNDEFINED: 0x00, // 000 (reserved)
BUS_ERROR: 0x04, // 004 illegal instructions, bus errors, stack limit, illegal internal address, microbreak
BUS_ERROR: 0x04, // 004 illegal instruction, unaligned address, invalid memory, stack limit, microbreak
RESERVED: 0x08, // 010 reserved instructions
BPT: 0x0C, // 014 BPT: breakpoint trap (trace)
IOT: 0x10, // 020 IOT: input/output trap

View file

@ -587,9 +587,10 @@ MemoryPDP11.prototype = {
*/
readNone: function readNone(off, addr) {
if (DEBUGGER && this.dbg && this.dbg.messageEnabled(MessagesPDP11.MEMORY) /* && !off */) {
this.dbg.printMessage("attempt to read invalid block %" + str.toHex(this.addr), true);
this.dbg.stopCPU();
this.dbg.printMessage("attempt to read invalid address " + this.dbg.toStrBase(addr), true);
this.dbg.stopInstruction();
}
this.bus.fault(addr, PDP11.ACCESS.READ);
return 0xff;
},
/**
@ -602,9 +603,10 @@ MemoryPDP11.prototype = {
*/
writeNone: function writeNone(off, v, addr) {
if (DEBUGGER && this.dbg && this.dbg.messageEnabled(MessagesPDP11.MEMORY) /* && !off */) {
this.dbg.printMessage("attempt to write " + str.toHexWord(v) + " to invalid block %" + str.toHex(this.addr), true);
this.dbg.stopCPU();
this.dbg.printMessage("attempt to write " + this.dbg.toStrBase(v) + " to invalid addresses " + this.dbg.toStrBase(addr), true);
this.dbg.stopInstruction();
}
this.bus.fault(addr, PDP11.ACCESS.WRITE);
},
/**
* readWordDefault(off, addr)
@ -653,7 +655,7 @@ MemoryPDP11.prototype = {
*/
readWordMemory: function readWordMemory(off, addr) {
if (PDP11.MEMFAULT && (off & 0x1)) {
this.bus.fault(addr);
this.bus.fault(addr, PDP11.ACCESS.READ_WORD);
}
if (BYTEARRAYS) {
return this.ab[off] | (this.ab[off + 1] << 8);
@ -697,7 +699,7 @@ MemoryPDP11.prototype = {
*/
writeWordMemory: function writeWordMemory(off, w, addr) {
if (PDP11.MEMFAULT && (off & 0x1)) {
this.bus.fault(addr);
this.bus.fault(addr, PDP11.ACCESS.WRITE_WORD);
}
if (BYTEARRAYS) {
this.ab[off] = (w & 0xff);
@ -807,7 +809,7 @@ MemoryPDP11.prototype = {
*/
readWordBE: function readWordBE(off, addr) {
if (PDP11.MEMFAULT && (off & 0x1)) {
this.bus.fault(addr);
this.bus.fault(addr, PDP11.ACCESS.READ_WORD);
}
return this.dv.getUint16(off, true);
},
@ -822,7 +824,7 @@ MemoryPDP11.prototype = {
readWordLE: function readWordLE(off, addr) {
var w;
if (PDP11.MEMFAULT && (off & 0x1)) {
this.bus.fault(addr);
this.bus.fault(addr, PDP11.ACCESS.READ_WORD);
}
/*
* TODO: For non-WORDBUS machines, it remains to be seen if there's any advantage to checking the offset
@ -875,7 +877,7 @@ MemoryPDP11.prototype = {
*/
writeWordBE: function writeWordBE(off, w, addr) {
if (PDP11.MEMFAULT && (off & 0x1)) {
this.bus.fault(addr);
this.bus.fault(addr, PDP11.ACCESS.WRITE_WORD);
}
this.dv.setUint16(off, w, true);
this.fDirty = true;
@ -890,7 +892,7 @@ MemoryPDP11.prototype = {
*/
writeWordLE: function writeWordLE(off, w, addr) {
if (PDP11.MEMFAULT && (off & 0x1)) {
this.bus.fault(addr);
this.bus.fault(addr, PDP11.ACCESS.WRITE_WORD);
}
/*
* TODO: For non-WORDBUS machines, it remains to be seen if there's any advantage to checking the offset