Added support for virtual read/write breakpoints; physical read/write breakpoints are still used if the specified address is physical (preceded by %) or is outside the virtual 16-bit address range
This commit is contained in:
parent
66ffe17659
commit
cb61219e22
5 changed files with 817 additions and 569 deletions
|
|
@ -189,15 +189,25 @@ CPUPDP11.prototype.initBus = function(cmp, bus, cpu, dbg)
|
|||
this.bus = bus;
|
||||
this.dbg = dbg;
|
||||
this.panel = cmp.panel;
|
||||
|
||||
for (var i = 0; i < CPUPDP11.BUTTONS.length; i++) {
|
||||
var control = this.bindings[CPUPDP11.BUTTONS[i]];
|
||||
if (control) this.cmp.setBinding(null, CPUPDP11.BUTTONS[i], control);
|
||||
}
|
||||
|
||||
this.init();
|
||||
this.setReady();
|
||||
};
|
||||
|
||||
/**
|
||||
* init()
|
||||
*
|
||||
* Stub for initialization call (overridden by the CPUStatePDP11 component).
|
||||
*
|
||||
* @this {CPUPDP11}
|
||||
*/
|
||||
CPUPDP11.prototype.init = function()
|
||||
{
|
||||
};
|
||||
|
||||
/**
|
||||
* finish()
|
||||
*
|
||||
|
|
|
|||
|
|
@ -159,11 +159,30 @@ CPUStatePDP11.prototype.initProcessor = function()
|
|||
this.aIRQs = []; // list of all IRQs, active or not (to be used for auto-configuration)
|
||||
|
||||
this.flags.complete = false;
|
||||
|
||||
this.nReadBreaks = this.nWriteBreaks = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* init()
|
||||
*
|
||||
* Called once the Bus has been initialized.
|
||||
*
|
||||
* @this {CPUStatePDP11}
|
||||
*/
|
||||
CPUStatePDP11.prototype.init = function()
|
||||
{
|
||||
this.getByteDirect = this.bus.getByte.bind(this.bus);
|
||||
this.getWordDirect = this.bus.getWord.bind(this.bus);
|
||||
this.setByteDirect = this.bus.setByte.bind(this.bus);
|
||||
this.setWordDirect = this.bus.setWord.bind(this.bus);
|
||||
};
|
||||
|
||||
/**
|
||||
* finish()
|
||||
*
|
||||
* Called before the CPU is powered up.
|
||||
*
|
||||
* TODO: This function simply ensures that we don't leave any IRQs installed with unresolved floating
|
||||
* (negative) vectors; however, properly assigning vectors according to device type (ie, auto-configuration)
|
||||
* is an exercise left for another day.
|
||||
|
|
@ -329,26 +348,35 @@ CPUStatePDP11.prototype.getMMUState = function()
|
|||
* Define handlers and DSPACE setting appropriate for the current MMU mode, in order to eliminate unnecessary calls
|
||||
* to mapVirtualToPhysical().
|
||||
*
|
||||
* TODO: We could further optimize readWord(), splitting it into readWordFromDSpace() and readWordFromISpace(),
|
||||
* eliminating the need to OR the addrDSpace bit when we know that bit is zero, but that's a pretty tiny optimization.
|
||||
*
|
||||
* @this {CPUStatePDP11}
|
||||
*/
|
||||
CPUStatePDP11.prototype.setMemoryAccess = function()
|
||||
{
|
||||
this.getByte = this.getByteDirect;
|
||||
this.getWord = this.getWordDirect;
|
||||
this.setByte = this.setByteDirect;
|
||||
this.setWord = this.setWordDirect;
|
||||
if (this.nReadBreaks) {
|
||||
this.getByte = this.getByteChecked;
|
||||
this.getWord = this.getWordChecked;
|
||||
}
|
||||
if (this.nWriteBreaks) {
|
||||
this.setByte = this.setByteChecked;
|
||||
this.setWord = this.setWordChecked;
|
||||
}
|
||||
if (this.mmuEnable) {
|
||||
this.addrDSpace = PDP11.ACCESS.DSPACE;
|
||||
this.addrIOPage = (this.regMMR3 & PDP11.MMR3.MMU_22BIT)? BusPDP11.IOPAGE_22BIT : BusPDP11.IOPAGE_18BIT;
|
||||
this.getAddr = this.getVirtualAddrByMode;
|
||||
this.readWord = this.readWordFromVirtual;
|
||||
this.writeWord = this.writeWordToVirtual;
|
||||
this.readWord = this.nReadBreaks? this.readWordFromVirtualChecked : this.readWordFromVirtual;
|
||||
this.writeWord = this.nWriteBreaks? this.writeWordToVirtualChecked : this.writeWordToVirtual;
|
||||
this.bus.setIOPageRange((this.regMMR3 & PDP11.MMR3.MMU_22BIT)? 22 : 18);
|
||||
} else {
|
||||
this.addrDSpace = 0;
|
||||
this.addrIOPage = BusPDP11.IOPAGE_16BIT;
|
||||
this.getAddr = this.getPhysicalAddrByMode;
|
||||
this.readWord = this.readWordFromPhysical;
|
||||
this.writeWord = this.writeWordToPhysical;
|
||||
this.readWord = this.nReadBreaks? this.readWordFromPhysicalChecked : this.readWordFromPhysical;
|
||||
this.writeWord = this.nWriteBreaks? this.writeWordToPhysicalChecked : this.writeWordToPhysical;
|
||||
this.bus.setIOPageRange(16);
|
||||
}
|
||||
};
|
||||
|
|
@ -2073,6 +2101,66 @@ CPUStatePDP11.prototype.checkStackLimit1145 = function(access, step, addr)
|
|||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* getByteChecked(addr)
|
||||
*
|
||||
* @this {CPUStatePDP11}
|
||||
* @param {number} addr
|
||||
* @return {number}
|
||||
*/
|
||||
CPUStatePDP11.prototype.getByteChecked = function(addr)
|
||||
{
|
||||
if (DEBUGGER && this.dbg) {
|
||||
this.dbg.checkMemoryRead(addr, 1);
|
||||
}
|
||||
return this.getByteDirect(addr);
|
||||
};
|
||||
|
||||
/**
|
||||
* getWordChecked(addr)
|
||||
*
|
||||
* @this {CPUStatePDP11}
|
||||
* @param {number} addr
|
||||
* @return {number}
|
||||
*/
|
||||
CPUStatePDP11.prototype.getWordChecked = function(addr)
|
||||
{
|
||||
if (DEBUGGER && this.dbg) {
|
||||
this.dbg.checkMemoryRead(addr, 2);
|
||||
}
|
||||
return this.getWordDirect(addr);
|
||||
};
|
||||
|
||||
/**
|
||||
* setByteChecked(addr, data)
|
||||
*
|
||||
* @this {CPUStatePDP11}
|
||||
* @param {number} addr
|
||||
* @param {number} data
|
||||
*/
|
||||
CPUStatePDP11.prototype.setByteChecked = function(addr, data)
|
||||
{
|
||||
if (DEBUGGER && this.dbg) {
|
||||
this.dbg.checkMemoryWrite(addr, 1);
|
||||
}
|
||||
this.setByteDirect(addr, data);
|
||||
};
|
||||
|
||||
/**
|
||||
* setWordChecked(addr, data)
|
||||
*
|
||||
* @this {CPUStatePDP11}
|
||||
* @param {number} addr
|
||||
* @param {number} data
|
||||
*/
|
||||
CPUStatePDP11.prototype.setWordChecked = function(addr, data)
|
||||
{
|
||||
if (DEBUGGER && this.dbg) {
|
||||
this.dbg.checkMemoryWrite(addr, 2);
|
||||
}
|
||||
this.setWordDirect(addr, data);
|
||||
};
|
||||
|
||||
/**
|
||||
* getByteSafe(addr)
|
||||
*
|
||||
|
|
@ -2102,7 +2190,7 @@ CPUStatePDP11.prototype.getByteSafe = function(addr)
|
|||
CPUStatePDP11.prototype.getWordSafe = function(addr)
|
||||
{
|
||||
this.nDisableTraps++;
|
||||
var w = this.readWord(addr);
|
||||
var w = this.bus.getWord(this.mapVirtualToPhysical(addr, PDP11.ACCESS.READ_WORD));
|
||||
this.nDisableTraps--;
|
||||
return w;
|
||||
};
|
||||
|
|
@ -2135,10 +2223,42 @@ CPUStatePDP11.prototype.setByteSafe = function(addr, data)
|
|||
CPUStatePDP11.prototype.setWordSafe = function(addr, data)
|
||||
{
|
||||
this.nDisableTraps++;
|
||||
this.writeWord(addr, data);
|
||||
this.bus.setWord(this.mapVirtualToPhysical(addr, PDP11.ACCESS.WRITE_WORD), data);
|
||||
this.nDisableTraps--;
|
||||
};
|
||||
|
||||
/**
|
||||
* addMemBreak(addr, fWrite)
|
||||
*
|
||||
* @this {CPUStatePDP11}
|
||||
* @param {number} addr
|
||||
* @param {boolean} fWrite is true for a memory write breakpoint, false for a memory read breakpoint
|
||||
*/
|
||||
CPUStatePDP11.prototype.addMemBreak = function(addr, fWrite)
|
||||
{
|
||||
if (DEBUGGER) {
|
||||
var nBreaks = fWrite? this.nWriteBreaks++ : this.nReadBreaks++;
|
||||
this.assert(nBreaks >= 0);
|
||||
if (!nBreaks) this.setMemoryAccess();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* removeMemBreak(addr, fWrite)
|
||||
*
|
||||
* @this {CPUStatePDP11}
|
||||
* @param {number} addr
|
||||
* @param {boolean} fWrite is true for a memory write breakpoint, false for a memory read breakpoint
|
||||
*/
|
||||
CPUStatePDP11.prototype.removeMemBreak = function(addr, fWrite)
|
||||
{
|
||||
if (DEBUGGER) {
|
||||
var nBreaks = fWrite? --this.nWriteBreaks : --this.nReadBreaks;
|
||||
this.assert(nBreaks >= 0);
|
||||
if (!nBreaks) this.setMemoryAccess();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* getPhysicalAddrByMode(mode, reg, access)
|
||||
*
|
||||
|
|
@ -2152,9 +2272,7 @@ CPUStatePDP11.prototype.setWordSafe = function(addr, data)
|
|||
*/
|
||||
CPUStatePDP11.prototype.getPhysicalAddrByMode = function(mode, reg, access)
|
||||
{
|
||||
var addr = this.getAddrByMode(mode, reg, access);
|
||||
if (addr >= BusPDP11.UNIBUS_22BIT) addr = this.mapUnibus(addr);
|
||||
return addr;
|
||||
return this.getAddrByMode(mode, reg, access);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -2184,10 +2302,26 @@ CPUStatePDP11.prototype.getVirtualAddrByMode = function(mode, reg, access)
|
|||
*/
|
||||
CPUStatePDP11.prototype.readWordFromPhysical = function(addr)
|
||||
{
|
||||
if (addr >= BusPDP11.UNIBUS_22BIT) addr = this.mapUnibus(addr);
|
||||
return this.bus.getWord(this.addrLast = addr);
|
||||
};
|
||||
|
||||
/**
|
||||
* readWordFromPhysicalChecked(addr)
|
||||
*
|
||||
* This is a handler set up by setMemoryAccess(). All calls should go through readWord().
|
||||
*
|
||||
* @this {CPUStatePDP11}
|
||||
* @param {number} addr
|
||||
* @return {number}
|
||||
*/
|
||||
CPUStatePDP11.prototype.readWordFromPhysicalChecked = function(addr)
|
||||
{
|
||||
if (DEBUGGER && this.dbg) {
|
||||
this.dbg.checkMemoryRead(addr, 2);
|
||||
}
|
||||
return this.readWordFromPhysical(addr);
|
||||
};
|
||||
|
||||
/**
|
||||
* readWordFromVirtual(addrVirtual)
|
||||
*
|
||||
|
|
@ -2202,6 +2336,23 @@ CPUStatePDP11.prototype.readWordFromVirtual = function(addrVirtual)
|
|||
return this.bus.getWord(this.addrLast = this.mapVirtualToPhysical(addrVirtual, PDP11.ACCESS.READ_WORD));
|
||||
};
|
||||
|
||||
/**
|
||||
* readWordFromVirtualChecked(addrVirtual)
|
||||
*
|
||||
* This is a handler set up by setMemoryAccess(). All calls should go through readWord().
|
||||
*
|
||||
* @this {CPUStatePDP11}
|
||||
* @param {number} addrVirtual (input address is 17 bit (I&D))
|
||||
* @return {number}
|
||||
*/
|
||||
CPUStatePDP11.prototype.readWordFromVirtualChecked = function(addrVirtual)
|
||||
{
|
||||
if (DEBUGGER && this.dbg) {
|
||||
this.dbg.checkMemoryRead(addrVirtual, 2);
|
||||
}
|
||||
return this.readWordFromVirtual(addrVirtual);
|
||||
};
|
||||
|
||||
/**
|
||||
* writeWordToPhysical(addr, data)
|
||||
*
|
||||
|
|
@ -2213,11 +2364,26 @@ CPUStatePDP11.prototype.readWordFromVirtual = function(addrVirtual)
|
|||
*/
|
||||
CPUStatePDP11.prototype.writeWordToPhysical = function(addr, data)
|
||||
{
|
||||
if (addr >= BusPDP11.UNIBUS_22BIT) addr = this.mapUnibus(addr);
|
||||
this.assert(!(data & ~0xffff));
|
||||
this.bus.setWord(this.addrLast = addr, data);
|
||||
};
|
||||
|
||||
/**
|
||||
* writeWordToPhysicalChecked(addr, data)
|
||||
*
|
||||
* This is a handler set up by setMemoryAccess(). All calls should go through writeWord().
|
||||
*
|
||||
* @this {CPUStatePDP11}
|
||||
* @param {number} addr
|
||||
* @param {number} data
|
||||
*/
|
||||
CPUStatePDP11.prototype.writeWordToPhysicalChecked = function(addr, data)
|
||||
{
|
||||
if (DEBUGGER && this.dbg) {
|
||||
this.dbg.checkMemoryWrite(addr, 2);
|
||||
}
|
||||
this.writeWordToPhysical(addr, data);
|
||||
};
|
||||
|
||||
/**
|
||||
* writeWordToVirtual(addrVirtual, data)
|
||||
*
|
||||
|
|
@ -2232,6 +2398,23 @@ CPUStatePDP11.prototype.writeWordToVirtual = function(addrVirtual, data)
|
|||
this.bus.setWord(this.addrLast = this.mapVirtualToPhysical(addrVirtual, PDP11.ACCESS.WRITE_WORD), data);
|
||||
};
|
||||
|
||||
/**
|
||||
* writeWordToVirtualChecked(addrVirtual, data)
|
||||
*
|
||||
* This is a handler set up by setMemoryAccess(). All calls should go through writeWord().
|
||||
*
|
||||
* @this {CPUStatePDP11}
|
||||
* @param {number} addrVirtual (input address is 17 bit (I&D))
|
||||
* @param {number} data
|
||||
*/
|
||||
CPUStatePDP11.prototype.writeWordToVirtualChecked = function(addrVirtual, data)
|
||||
{
|
||||
if (DEBUGGER && this.dbg) {
|
||||
this.dbg.checkMemoryWrite(addrVirtual, 2);
|
||||
}
|
||||
this.writeWordToVirtual(addrVirtual, data);
|
||||
};
|
||||
|
||||
/**
|
||||
* readWordFromPrevSpace(opCode, access)
|
||||
*
|
||||
|
|
@ -2287,14 +2470,14 @@ CPUStatePDP11.prototype.writeWordToPrevSpace = function(opCode, access, data)
|
|||
if (!(access & PDP11.ACCESS.DSPACE)) addr &= 0xffff;
|
||||
/*
|
||||
* TODO: Consider replacing the following code with writeWord(), by adding optional pswMode
|
||||
* parameters for each of the discrete mapVirtualToPhysical() and bus.setWord() operations, because
|
||||
* parameters for each of the discrete mapVirtualToPhysical() and setWord() operations, because
|
||||
* as it stands, this is the only remaining call to mapVirtualToPhysical() outside of our
|
||||
* setMemoryAccess() handlers.
|
||||
*/
|
||||
this.pswMode = (this.regPSW >> 12) & 3;
|
||||
addr = this.mapVirtualToPhysical(addr | (access & PDP11.ACCESS.DSPACE), PDP11.ACCESS.WRITE);
|
||||
this.pswMode = (this.regPSW >> 14) & 3;
|
||||
this.bus.setWord(addr, data);
|
||||
this.setWord(addr, data);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -2319,7 +2502,7 @@ CPUStatePDP11.prototype.readSrcByte = function(opCode)
|
|||
if (!mode) {
|
||||
result = this.regsGen[reg + this.offRegSrc] & this.maskRegSrcByte;
|
||||
} else {
|
||||
result = this.bus.getByte(this.getAddr(mode, reg, PDP11.ACCESS.READ_BYTE));
|
||||
result = this.getByte(this.getAddr(mode, reg, PDP11.ACCESS.READ_BYTE));
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
|
@ -2361,7 +2544,7 @@ CPUStatePDP11.prototype.readSrcWord = function(opCode)
|
|||
if (!mode) {
|
||||
result = this.regsGen[reg + this.offRegSrc];
|
||||
} else {
|
||||
result = this.bus.getWord(this.getAddr(mode, reg, PDP11.ACCESS.READ_WORD));
|
||||
result = this.getWord(this.getAddr(mode, reg, PDP11.ACCESS.READ_WORD));
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
|
@ -2395,7 +2578,7 @@ CPUStatePDP11.prototype.readDstByte = function(opCode)
|
|||
if (!mode) {
|
||||
result = this.regsGen[reg] & 0xff;
|
||||
} else {
|
||||
result = this.bus.getByte(this.getAddr(mode, reg, PDP11.ACCESS.READ_BYTE));
|
||||
result = this.getByte(this.getAddr(mode, reg, PDP11.ACCESS.READ_BYTE));
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
|
@ -2415,7 +2598,7 @@ CPUStatePDP11.prototype.readDstWord = function(opCode)
|
|||
if (!mode) {
|
||||
result = this.regsGen[reg];
|
||||
} else {
|
||||
result = this.bus.getWord(this.getAddr(mode, reg, PDP11.ACCESS.READ_WORD));
|
||||
result = this.getWord(this.getAddr(mode, reg, PDP11.ACCESS.READ_WORD));
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
|
@ -2441,7 +2624,7 @@ CPUStatePDP11.prototype.updateDstByte = function(opCode, data, fnOp)
|
|||
} else {
|
||||
var addr = this.dstAddr = this.getAddr(mode, reg, PDP11.ACCESS.UPDATE_BYTE);
|
||||
data = (data < 0? (this.regsGen[-data-1] & 0xff) : data);
|
||||
this.bus.setByte(addr, fnOp.call(this, data, this.bus.getByte(addr)));
|
||||
this.setByte(addr, fnOp.call(this, data, this.getByte(addr)));
|
||||
if (addr & 1) this.nStepCycles--;
|
||||
}
|
||||
};
|
||||
|
|
@ -2467,7 +2650,7 @@ CPUStatePDP11.prototype.updateDstWord = function(opCode, data, fnOp)
|
|||
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, data < 0? this.regsGen[-data-1] : data, this.bus.getWord(addr)));
|
||||
this.setWord(addr, fnOp.call(this, data < 0? this.regsGen[-data-1] : data, this.getWord(addr)));
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -2505,7 +2688,7 @@ CPUStatePDP11.prototype.writeDstByte = function(opCode, data, writeFlags, fnFlag
|
|||
} else {
|
||||
var addr = this.getAddr(mode, reg, PDP11.ACCESS.WRITE_BYTE);
|
||||
fnFlags.call(this, (data = data < 0? (this.regsGen[-data-1] & 0xff) : data) << 8);
|
||||
this.bus.setByte(addr, data);
|
||||
this.setByte(addr, data);
|
||||
if (addr & 1) this.nStepCycles--;
|
||||
}
|
||||
};
|
||||
|
|
@ -2533,7 +2716,7 @@ CPUStatePDP11.prototype.writeDstWord = function(opCode, data, fnFlags)
|
|||
} else {
|
||||
var addr = this.getAddr(mode, reg, PDP11.ACCESS.WRITE_WORD);
|
||||
fnFlags.call(this, (data = data < 0? this.regsGen[-data-1] : data));
|
||||
this.bus.setWord(addr, data);
|
||||
this.setWord(addr, data);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -895,7 +895,7 @@ if (DEBUGGER) {
|
|||
*/
|
||||
DebuggerPDP11.prototype.toStrAddr = function(dbgAddr)
|
||||
{
|
||||
return this.toStrOffset(dbgAddr.addr);
|
||||
return (dbgAddr.fPhysical? '%' : '') + this.toStrOffset(dbgAddr.addr);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -943,8 +943,8 @@ if (DEBUGGER) {
|
|||
n = 1;
|
||||
}
|
||||
|
||||
this.println("blockid physical blockaddr used size type");
|
||||
this.println("-------- --------- ---------- ------ ------ ----");
|
||||
this.println("blockid physical blockaddr used size type");
|
||||
this.println("-------- --------- --------- ------ ------ ----");
|
||||
|
||||
var typePrev = -1, cPrev = 0;
|
||||
while (n--) {
|
||||
|
|
@ -955,7 +955,7 @@ if (DEBUGGER) {
|
|||
typePrev = block.type;
|
||||
var sType = MemoryPDP11.TYPE_NAMES[typePrev];
|
||||
if (block) {
|
||||
this.println(str.toHex(block.id, 8) + " %" + str.toHex(i << this.bus.nBlockShift, 8) + " %%" + str.toHex(block.addr, 8) + " " + str.toHexWord(block.used) + " " + str.toHexWord(block.size) + " " + sType);
|
||||
this.println(str.toHex(block.id, 8) + " %" + str.toHex(i << this.bus.nBlockShift, 8) + " %" + str.toHex(block.addr, 8) + " " + str.toHexWord(block.used) + " " + str.toHexWord(block.size) + " " + sType);
|
||||
}
|
||||
if (typePrev != MemoryPDP11.TYPE.NONE) typePrev = -1;
|
||||
cPrev = 0;
|
||||
|
|
@ -1731,12 +1731,40 @@ if (DEBUGGER) {
|
|||
var cpu = this.cpu;
|
||||
|
||||
/*
|
||||
* Since opHalt() will rewind the PC on a HALT, purely for our debugging benefit, we must compensate
|
||||
* for that here by skipping over the HALT if/when the machine starts up again.
|
||||
* If opHalt() calls our stopInstruction() function, it will effectively rewind the PC back to the HALT,
|
||||
* purely for our debugging benefit, so we must compensate for that here by advancing the PC past the HALT
|
||||
* when the machine starts up again.
|
||||
*/
|
||||
if (!nState) {
|
||||
opCode = this.cpu.getWordSafe(addr);
|
||||
if (opCode == PDP11.OPCODE.HALT) {
|
||||
/*
|
||||
* We have to be careful about this HALT-skipping code, because as fate would have it, I inadvertently
|
||||
* stopped the following diagnostic with a breakpoint *on* a HALT instruction:
|
||||
*
|
||||
* .R EKBEE1
|
||||
* EKBEE1.BIC
|
||||
*
|
||||
* CEKBEE0 11/70 MEM MGMT
|
||||
*
|
||||
* CPU UNDER TEST FOUND TO BE A KB11-CM
|
||||
* bp 033330 hit
|
||||
* stopped (28339757 instructions, 123994176 cycles, 19177 ms, 6465775 hz)
|
||||
* R0=140000 R1=033330 R2=100143 R3=133260 R4=000000 R5=177700
|
||||
* SP=000600 PC=033330 PS=140000 IR=000000 SL=000377 T0 N0 Z0 V0 C0
|
||||
* 033330: 000000 HALT
|
||||
*
|
||||
* Since we haven't executed the HALT yet, it would be wrong (and would cause a diagnostic failure) to
|
||||
* skip over it. In this particular case, the PDR for the address of the HALT instruction was invalid,
|
||||
* so the HALT gets fetched but not executed.
|
||||
*
|
||||
* My first thought was that maybe we need to probe the address more thoroughly (getWordSafe() does
|
||||
* not), but it should be sufficient to simply confirm that the PC of the last opcode executed matches
|
||||
* the addr of this HALT.
|
||||
*
|
||||
* Yes, I could save myself this grief by eliminating these PC hacks, both here and in stopInstruction(),
|
||||
* but I still think it's a useful debugging aid.
|
||||
*/
|
||||
if (opCode == PDP11.OPCODE.HALT && this.cpu.getLastPC() == addr) {
|
||||
addr = this.cpu.advancePC(2);
|
||||
}
|
||||
}
|
||||
|
|
@ -1873,19 +1901,29 @@ if (DEBUGGER) {
|
|||
*/
|
||||
DebuggerPDP11.prototype.clearBreakpoints = function()
|
||||
{
|
||||
var i, dbgAddr;
|
||||
var i, dbgAddr, addr;
|
||||
this.aBreakExec = ["bp"];
|
||||
if (this.aBreakRead !== undefined) {
|
||||
for (i = 1; i < this.aBreakRead.length; i++) {
|
||||
dbgAddr = this.aBreakRead[i];
|
||||
this.bus.removeMemBreak(this.getAddr(dbgAddr), false);
|
||||
addr = this.getAddr(dbgAddr);
|
||||
if (!dbgAddr.fPhysical) {
|
||||
this.cpu.removeMemBreak(addr, false);
|
||||
} else {
|
||||
this.bus.removeMemBreak(addr, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
this.aBreakRead = ["br"];
|
||||
if (this.aBreakWrite !== undefined) {
|
||||
for (i = 1; i < this.aBreakWrite.length; i++) {
|
||||
dbgAddr = this.aBreakWrite[i];
|
||||
this.bus.removeMemBreak(this.getAddr(dbgAddr), true);
|
||||
addr = this.getAddr(dbgAddr);
|
||||
if (!dbgAddr.fPhysical) {
|
||||
this.cpu.removeMemBreak(addr, true);
|
||||
} else {
|
||||
this.bus.removeMemBreak(addr, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
this.aBreakWrite = ["bw"];
|
||||
|
|
@ -1947,7 +1985,17 @@ if (DEBUGGER) {
|
|||
this.println("invalid address: " + this.toStrAddr(dbgAddr));
|
||||
fSuccess = false;
|
||||
} else {
|
||||
this.bus.addMemBreak(addr, aBreak == this.aBreakWrite);
|
||||
var fWrite = (aBreak == this.aBreakWrite);
|
||||
/*
|
||||
* We automatically promote any read/write breakpoint address to fPhysical if it's
|
||||
* outside the 16-bit virtual address range.
|
||||
*/
|
||||
if (addr > 0xffff) dbgAddr.fPhysical = true;
|
||||
if (!dbgAddr.fPhysical) {
|
||||
this.cpu.addMemBreak(addr, fWrite);
|
||||
} else {
|
||||
this.bus.addMemBreak(addr, fWrite);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1993,7 +2041,12 @@ if (DEBUGGER) {
|
|||
}
|
||||
aBreak.splice(i, 1);
|
||||
if (aBreak != this.aBreakExec) {
|
||||
this.bus.removeMemBreak(addr, aBreak == this.aBreakWrite);
|
||||
var fWrite = (aBreak == this.aBreakWrite);
|
||||
if (!dbgAddrBreak.fPhysical) {
|
||||
this.cpu.removeMemBreak(addr, fWrite);
|
||||
} else {
|
||||
this.bus.removeMemBreak(addr, fWrite);
|
||||
}
|
||||
}
|
||||
/*
|
||||
* We'll mirror the logic in addBreakpoint() and leave the history buffer alone if this
|
||||
|
|
|
|||
Loading…
Reference in a new issue