Fixed some breakpoint issues, and honored the RK11 IBA bit

This commit is contained in:
Jeff Parsons 2016-12-06 10:47:36 -08:00 committed by Jeff Parsons
commit 66ffe17659
9 changed files with 562 additions and 611 deletions

View file

@ -235,10 +235,6 @@ BusPDP11.IOController = {
var bus = this.controller;
var afn = bus.aIOHandlers[off];
if (DEBUGGER && this.dbg) {
this.dbg.checkMemoryRead(addr, 1);
}
/*
* Since addr is primarily used to advise an I/O handler of the target IOPAGE address, and since we don't want
* our handlers to worry about the current IOPAGE location, we truncate addr to 16 bits (the IOPAGE's lowest location).
@ -299,10 +295,6 @@ BusPDP11.IOController = {
var bus = this.controller;
var afn = bus.aIOHandlers[off];
if (DEBUGGER && this.dbg) {
this.dbg.checkMemoryWrite(addr, 1);
}
/*
* Since addr is primarily used to advise an I/O handler of the target IOPAGE address, and since we don't want
* our handlers to worry about the current IOPAGE location, we truncate addr to 16 bits (the IOPAGE's lowest location).
@ -381,10 +373,6 @@ BusPDP11.IOController = {
var bus = this.controller;
var afn = bus.aIOHandlers[off];
if (DEBUGGER && this.dbg) {
this.dbg.checkMemoryRead(addr, 2);
}
/*
* Since addr is primarily used to advise an I/O handler of the target IOPAGE address, and since we don't want
* our handlers to worry about the current IOPAGE location, we truncate addr to 16 bits (the IOPAGE's lowest location).
@ -426,10 +414,6 @@ BusPDP11.IOController = {
var bus = this.controller;
var afn = bus.aIOHandlers[off];
if (DEBUGGER && this.dbg) {
this.dbg.checkMemoryWrite(addr, 2);
}
/*
* Since addr is primarily used to advise an I/O handler of the target IOPAGE address, and since we don't want
* our handlers to worry about the current IOPAGE location, we truncate addr to 16 bits (the IOPAGE's lowest location).
@ -1356,7 +1340,7 @@ BusPDP11.prototype.getAddrByName = function(sName)
var off = +i;
var afn = this.aIOHandlers[off];
if (afn[BusPDP11.IOHANDLER.REG_NAME] == sName) {
return off + this.addrIOPage;
return this.addrIOPage + off;
}
}
return null;

View file

@ -1822,31 +1822,6 @@ CPUStatePDP11.prototype.mapVirtualToPhysical = function(addrVirtual, access)
return addr;
};
/**
* readByteFromPhysical(addr)
*
* @this {CPUStatePDP11}
* @param {number} addr
* @return {number}
*/
CPUStatePDP11.prototype.readByteFromPhysical = function(addr)
{
return this.bus.getByte(addr);
};
/**
* writeByteToPhysical(addr, data)
*
* @this {CPUStatePDP11}
* @param {number} addr
* @param {number} data
*/
CPUStatePDP11.prototype.writeByteToPhysical = function(addr, data)
{
if (addr & 1) this.nStepCycles--;
this.bus.setByte(addr, data);
};
/**
* popWord()
*
@ -2110,7 +2085,7 @@ CPUStatePDP11.prototype.checkStackLimit1145 = function(access, step, addr)
CPUStatePDP11.prototype.getByteSafe = function(addr)
{
this.nDisableTraps++;
var b = this.readByteFromPhysical(this.mapVirtualToPhysical(addr, PDP11.ACCESS.READ_BYTE));
var b = this.bus.getByte(this.mapVirtualToPhysical(addr, PDP11.ACCESS.READ_BYTE));
this.nDisableTraps--;
return b;
};
@ -2127,7 +2102,7 @@ CPUStatePDP11.prototype.getByteSafe = function(addr)
CPUStatePDP11.prototype.getWordSafe = function(addr)
{
this.nDisableTraps++;
var w = this.readWordFromPhysical(this.mapVirtualToPhysical(addr, PDP11.ACCESS.READ_WORD));
var w = this.readWord(addr);
this.nDisableTraps--;
return w;
};
@ -2144,7 +2119,7 @@ CPUStatePDP11.prototype.getWordSafe = function(addr)
CPUStatePDP11.prototype.setByteSafe = function(addr, data)
{
this.nDisableTraps++;
this.writeByteToPhysical(this.mapVirtualToPhysical(addr, PDP11.ACCESS.WRITE_BYTE), data);
this.bus.setByte(this.mapVirtualToPhysical(addr, PDP11.ACCESS.WRITE_BYTE), data);
this.nDisableTraps--;
};
@ -2160,7 +2135,7 @@ CPUStatePDP11.prototype.setByteSafe = function(addr, data)
CPUStatePDP11.prototype.setWordSafe = function(addr, data)
{
this.nDisableTraps++;
this.writeWordToPhysical(this.mapVirtualToPhysical(addr, PDP11.ACCESS.WRITE_WORD), data);
this.writeWord(addr, data);
this.nDisableTraps--;
};
@ -2344,7 +2319,7 @@ CPUStatePDP11.prototype.readSrcByte = function(opCode)
if (!mode) {
result = this.regsGen[reg + this.offRegSrc] & this.maskRegSrcByte;
} else {
result = this.readByteFromPhysical(this.getAddr(mode, reg, PDP11.ACCESS.READ_BYTE));
result = this.bus.getByte(this.getAddr(mode, reg, PDP11.ACCESS.READ_BYTE));
}
return result;
};
@ -2420,7 +2395,7 @@ CPUStatePDP11.prototype.readDstByte = function(opCode)
if (!mode) {
result = this.regsGen[reg] & 0xff;
} else {
result = this.readByteFromPhysical(this.getAddr(mode, reg, PDP11.ACCESS.READ_BYTE));
result = this.bus.getByte(this.getAddr(mode, reg, PDP11.ACCESS.READ_BYTE));
}
return result;
};
@ -2466,7 +2441,8 @@ 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.writeByteToPhysical(addr, fnOp.call(this, data, this.readByteFromPhysical(addr)));
this.bus.setByte(addr, fnOp.call(this, data, this.bus.getByte(addr)));
if (addr & 1) this.nStepCycles--;
}
};
@ -2529,7 +2505,8 @@ 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.writeByteToPhysical(addr, data);
this.bus.setByte(addr, data);
if (addr & 1) this.nStepCycles--;
}
};

View file

@ -2087,8 +2087,8 @@ if (DEBUGGER) {
DebuggerPDP11.prototype.checkBreakpoint = function(addr, nb, aBreak, fTemporary)
{
/*
* Time to check for execution breakpoints; note that this should be done BEFORE updating
* history data (see checkInstruction), since we might not actually execute the current instruction.
* Time to check for breakpoints; note that this should be done BEFORE updating history data
* (see checkInstruction), since we might not actually execute the current instruction.
*/
var fBreak = false;
@ -2101,11 +2101,11 @@ if (DEBUGGER) {
if (fTemporary && !dbgAddrBreak.fTemporary) continue;
/*
* Since we're checking an execution address, which is always virtual, and virtual
* If we're checking an execution address, which is always virtual, and virtual
* addresses are always restricted to 16 bits, let's mask the breakpoint address to match
* (the user should know better, but we'll be nice).
*/
var addrBreak = this.getAddr(dbgAddrBreak) & 0xffff;
var addrBreak = this.getAddr(dbgAddrBreak) & (aBreak == this.aBreakExec? 0xffff : -1);
for (var n = 0; n < nb; n++) {
if ((addr + n) != addrBreak) continue;
@ -3134,33 +3134,35 @@ if (DEBUGGER) {
*
* 00,010,011,000,100,010 00000023042
* 0,011,000,100,010 00000003042
* + KIPAR[1]: 0,000,001,101,111,010,000,000 00000157200
* & MMU MASK: 1,111,111,111,111,111,111,111 00017777777
* + KIPAR1: 0,000,001,101,111,010,000,000 00000157200
* & MMUMASK: 1,111,111,111,111,111,111,111 00017777777
* = PHYSICAL: 0,000,001,110,010,010,100,010 00000162242
*/
var a = this.cpu.getAddrInfo(dbgAddr.addr);
this.println(str.pad("", 19) + str.toBin(dbgAddr.addr, 17, 3) + " " + str.toOct(dbgAddr.addr, 8));
if (a.length > 1) {
this.println(str.pad("", 24) + str.toBin(a[1], 13, 3) + " " + str.toOct(a[1], 8));
this.println("+ " + DebuggerPDP11.MODES[a[2]] + "PAR[" + a[3] + "]: " + str.toBin(a[4], 22, 3) + " " + str.toOct(a[4], 8));
this.println("& MMU MASK: " + str.toBin(a[5], 22, 3) + " " + str.toOct(a[5], 8));
this.println("+ " + DebuggerPDP11.MODES[a[2]] + "PAR" + a[3] + ": " + str.toBin(a[4], 22, 3) + " " + str.toOct(a[4], 8));
this.println("& MMUMASK: " + str.toBin(a[5], 22, 3) + " " + str.toOct(a[5], 8));
this.println("= PHYSICAL: " + str.toBin(a[0], 22, 3) + " " + str.toOct(a[0], 8))
}
return;
}
var len = 0; // 0 is not a default; it triggers the appropriate default below
var fRange = false;
var len = 0;
var fJSON = (sCmd == "ds");
if (sLen) {
fRange = true;
if (sLen.charAt(0) == 'l') {
fRange = false;
sLen = sLen.substr(1) || sBytes;
len = this.parseValue(sLen);
}
len = this.parseValue(sLen) >>> 0; // negative lengths not allowed
if (len > 0x10000) len = 0x10000; // prevent bad user (or variable) input from producing excessive output
else {
var dbgAddrEnd = this.parseAddr(sLen);
if (dbgAddrEnd) len = dbgAddrEnd.addr - dbgAddr.addr;
}
if (len < 0) len = 0;
if (len > 0x10000) len = 0x10000;
}
/*
@ -3168,7 +3170,7 @@ if (DEBUGGER) {
* since this is primarily a word-oriented machine.
*/
var size = (sCmd == "dd"? 4 : (sCmd == "db"? 1 : 2));
var nBytes = (fRange? (len - dbgAddr.addr) : (size * len)) || 128;
var nBytes = (size * len) || 128;
var nBytesPerLine = fJSON? 16 : this.nBase;
var nLines = (((nBytes + nBytesPerLine - 1) / nBytesPerLine)|0) || 1;

View file

@ -163,10 +163,10 @@ var PDP11 = {
* Processor modes
*/
MODE: {
KERNEL: 0x0,
SUPER: 0x1,
KERNEL: 0x0, // 11/40 and higher only
SUPER: 0x1, // 11/45 and higher only
UNUSED: 0x2,
USER: 0x3,
USER: 0x3, // 11/40 and higher only
MASK: 0x3
},
/*
@ -503,44 +503,33 @@ var PDP11 = {
KDPAR5: 0o172372, // Kernel D Page Address Register 5
KDPAR6: 0o172374, // Kernel D Page Address Register 6
KDPAR7: 0o172376, // Kernel D Page Address Register 7
MMR3: 0o172516, // 772516 17772516
RLCS: 0o174400, // RL11 Control Status Register
RLBA: 0o174402, // RL11 Bus Address Register
RLDA: 0o174404, // RL11 Disk Address Register
RLMP: 0o174406, // RL11 Multi-Purpose Register
RLBE: 0o174410, // RL11 Bus (Address) Extension Register (RLV12 controller only)
DL11: 0o176500, // DL11 Additional Register Range (ends at 0o176676)
RKDS: 0o177400, // RK11 Drive Status Register
RKER: 0o177402, // RK11 Error Register
RKCS: 0o177404, // RK11 Control Status Register
RKWC: 0o177406, // RK11 Word Count Register
RKBA: 0o177410, // RK11 Bus Address Register
RKDA: 0o177412, // RK11 Disk Address Register
// NOTE: 177414 is unused
RKDB: 0o177416, // RK11 Data Buffer Register
LKS: 0o177546, // KW11-L Clock Status
PRS: 0o177550, // PC11 (and PR11) Reader Status Register
PRB: 0o177552, // PC11 (and PR11) Reader Buffer Register
PPS: 0o177554, // PC11 Punch Status Register
PPB: 0o177556, // PC11 Punch Buffer Register
RCSR: 0o177560, // DL11 Receiver Status Register
RBUF: 0o177562, // DL11 Receiver Data Buffer Register
XCSR: 0o177564, // DL11 Transmitter Status Register
XBUF: 0o177566, // DL11 Transmitter Data Buffer Register
CNSW: 0o177570, // Console (Front Panel) Switch/Display Register
MMR0: 0o177572, // 777572 17777572
MMR1: 0o177574, // 777574 17777574
MMR2: 0o177576, // 777576 17777576
UIPDR0: 0o177600, // User I Page Descriptor Register 0
UIPDR1: 0o177602, // User I Page Descriptor Register 1
UIPDR2: 0o177604, // User I Page Descriptor Register 2
@ -573,7 +562,6 @@ var PDP11 = {
UDPAR5: 0o177672, // User D Page Address Register 5
UDPAR6: 0o177674, // User D Page Address Register 6
UDPAR7: 0o177676, // User D Page Address Register 7
R0SET0: 0o177700, //
R1SET0: 0o177701, //
R2SET0: 0o177702, //
@ -590,7 +578,6 @@ var PDP11 = {
R5SET1: 0o177715, //
R6SUPER: 0o177716, //
R6USER: 0o177717, //
/*
* This next group of registers is largely ignored; all accesses are routed to regsControl[],
* and therefore are managed as a block of 8 "CTRL" registers.
@ -602,9 +589,8 @@ var PDP11 = {
CACHEC: 0o177746, // Cache Control (11/70 only)
MAINT: 0o177750, // Maintenance (11/70 only)
HITMISS: 0o177752, // Hit/Miss (11/70 only)
UNDEF1: 0o177754,
UNDEF2: 0o177756,
UNDEF1: 0o177754, //
UNDEF2: 0o177756, //
LSIZE: 0o177760, // Lower Size Register (last 64-byte block #) (11/70 only)
HSIZE: 0o177762, // Upper Size Register (always zero) (11/70 only)
SYSID: 0o177764, // System ID Register (11/70 only)
@ -654,7 +640,7 @@ var PDP11 = {
BAUD: 9600
},
XBUF: { // 177566: DL11 Transmitter Data Buffer Register
DATA: 0x00FF // Transmitted Data (W/O) TODO: Determine why pdp11.js effectively defined this as 0x7F
DATA: 0x00FF // Transmitted Data (W/O) (TODO: Determine why pdp11.js effectively defined this as 0x7F)
}
},
KW11: { // KW11-L Line Time Clock (60Hz; well, OK, or 50Hz, if you're in the UK, I suppose...)
@ -778,7 +764,7 @@ var PDP11 = {
RL11: { // RL11 Disk Controller
PRI: 5,
VEC: 0o160,
RLCS: { // Control Status Register (174400)
RLCS: { // 174400: Control Status Register
DRDY: 0x0001, // Drive Ready (R/O)
FUNC: 0x000E, // Function Code (F2,F1,F0) (R/W)
BAE: 0x0030, // Bus Address Extension bits (BA17,BA16) (R/W)
@ -798,13 +784,13 @@ var PDP11 = {
DS: 8
}
},
RLBA: { // Bus Address Register (174402)
RLBA: { // 174402: Bus Address Register
WMASK: 0xFFFE // bit 0 is effectively not writable (always zero)
},
/*
* This register has 3 formats: one for Seek, another for Read/Write, and a third for Get Status
*/
RLDA: { // Disk Address Register (174404)
RLDA: { // 174404: Disk Address Register
SEEK_CMD: 0x0001, // Seek: bit 0 must be set, bits 1 and 3 must be clear
SEEK_DIR: 0x0004, // Direction (clear to move heads away from spindle (lower cylinder), set to move to higher cylinder)
SEEK_HS: 0x0010, // Head Select (clear to select upper head, set to select lower head)
@ -822,7 +808,7 @@ var PDP11 = {
/*
* This register has 3 formats: one for Read Header, another for Read/Write, and a third for Get Status
*/
RLMP: { // Multi-Purpose Register (177406)
RLMP: { // 177406: Multi-Purpose Register
GS_ST: { // Major State Code (of the drive)
LOADC: 0x0, // Load Cartridge
SPINUP: 0x1, // Spin-Up
@ -847,7 +833,7 @@ var PDP11 = {
GS_CHE: 0x4000, // Current Head Error
GS_WDE: 0x8000 // Write Data Error
},
RLBE: { // Bus (Address) Extension Register (174410)
RLBE: { // 174410: Bus (Address) Extension Register
MASK: 0x003F // bits 5-0 correspond to bus address bits 21-16
},
ERRC: { // NOTE: These error codes are pre-shifted to read/write directly from/to RLCS.ERRC

View file

@ -572,7 +572,7 @@ RK11.prototype.bootSelectedDisk = function()
* a READY state is assured, and the readData() call shouldn't do anything to change that.
*/
this.cpu.setReset(0, true);
var err = this.readData(drive, 0, 0, 0, 512, 0);
var err = this.readData(drive, 0, 0, 0, 512, 0x0000, 2);
if (err) {
this.notice("Unable to read the boot sector (" + err + ")");
}
@ -954,7 +954,7 @@ RK11.prototype.processCommand = function()
var fnReadWrite, sFunc = "";
var iDrive = (this.regRKDA & PDP11.RK11.RKDA.DS) >> PDP11.RK11.RKDA.SHIFT.DS;
var drive = this.aDrives[iDrive];
var iCylinder, iHead, iSector, nWords, addr;
var iCylinder, iHead, iSector, nWords, addr, inc;
this.regRKCS &= ~PDP11.RK11.RKCS.CRDY;
var func = (this.regRKCS & PDP11.RK11.RKCS.FUNC) >> PDP11.RK11.RKCS.SHIFT.FUNC;
@ -999,8 +999,9 @@ RK11.prototype.processCommand = function()
iSector = this.regRKDA & PDP11.RK11.RKDA.SA;
nWords = (0x10000 - this.regRKWC) & 0xffff;
addr = (((this.regRKCS & PDP11.RK11.RKCS.MEX)) << (16 - PDP11.RK11.RKCS.SHIFT.MEX)) | this.regRKBA;
inc = (this.regRKCS & PDP11.RK11.RKCS.IBA)? 0 : 2;
if (this.messageEnabled()) this.printMessage(this.type + ": " + sFunc + "(" + iCylinder + ":" + iHead + ":" + iSector + ") @" + str.toOct(addr) + "-" + str.toOct(addr + ((nWords - 1) << 1)), true);
if (this.messageEnabled()) this.printMessage(this.type + ": " + sFunc + "(" + iCylinder + ":" + iHead + ":" + iSector + ") " + str.toOct(addr) + "-" + str.toOct(addr + ((nWords - 1) << 1)), true, true);
if (iCylinder >= drive.nCylinders) {
this.regRKER |= PDP11.RK11.RKER.DRE | PDP11.RK11.RKER.NXC;
@ -1013,7 +1014,7 @@ RK11.prototype.processCommand = function()
break;
}
fInterrupt = fnReadWrite.call(this, drive, iCylinder, iHead, iSector, nWords, addr, (func >= PDP11.RK11.FUNC.WCHK), this.endReadWrite.bind(this));
fInterrupt = fnReadWrite.call(this, drive, iCylinder, iHead, iSector, nWords, addr, inc, (func >= PDP11.RK11.FUNC.WCHK), this.endReadWrite.bind(this));
break;
case PDP11.RK11.FUNC.DRESET:
@ -1064,7 +1065,7 @@ RK11.prototype.endReadWrite = function(err, iCylinder, iHead, iSector, nWords, a
};
/**
* readData(drive, iCylinder, iHead, iSector, nWords, addr, fCheck, done)
* readData(drive, iCylinder, iHead, iSector, nWords, addr, inc, fCheck, done)
*
* @this {RK11}
* @param {Object} drive
@ -1073,11 +1074,12 @@ RK11.prototype.endReadWrite = function(err, iCylinder, iHead, iSector, nWords, a
* @param {number} iSector
* @param {number} nWords
* @param {number} addr
* @param {number} inc (normally 2, unless inhibited, in which case it's 0)
* @param {boolean} [fCheck]
* @param {function(...)} [done]
* @return {boolean|number} true if complete, false if queued (or if no done() is supplied, the error code, if any)
*/
RK11.prototype.readData = function(drive, iCylinder, iHead, iSector, nWords, addr, fCheck, done)
RK11.prototype.readData = function(drive, iCylinder, iHead, iSector, nWords, addr, inc, fCheck, done)
{
var err = 0;
var disk = drive.disk;
@ -1119,7 +1121,7 @@ RK11.prototype.readData = function(drive, iCylinder, iHead, iSector, nWords, add
break;
}
}
addr += 2;
addr += inc;
if (ibSector >= disk.cbSector) {
sector = null;
if (++iSector >= disk.nSectors) {
@ -1138,7 +1140,7 @@ RK11.prototype.readData = function(drive, iCylinder, iHead, iSector, nWords, add
};
/**
* writeData(drive, iCylinder, iHead, iSector, nWords, addr, fCheck, done)
* writeData(drive, iCylinder, iHead, iSector, nWords, addr, inc, fCheck, done)
*
* @this {RK11}
* @param {Object} drive
@ -1147,11 +1149,12 @@ RK11.prototype.readData = function(drive, iCylinder, iHead, iSector, nWords, add
* @param {number} iSector
* @param {number} nWords
* @param {number} addr
* @param {number} inc (normally 2, unless inhibited, in which case it's 0)
* @param {boolean} [fCheck]
* @param {function(...)} [done]
* @return {boolean|number} true if complete, false if queued (or if no done() is supplied, the error code, if any)
*/
RK11.prototype.writeData = function(drive, iCylinder, iHead, iSector, nWords, addr, fCheck, done)
RK11.prototype.writeData = function(drive, iCylinder, iHead, iSector, nWords, addr, inc, fCheck, done)
{
var err = 0;
var disk = drive.disk;
@ -1168,7 +1171,7 @@ RK11.prototype.writeData = function(drive, iCylinder, iHead, iSector, nWords, ad
err = PDP11.RK11.RKER.NXM;
break;
}
addr += 2;
addr += inc;
if (!sector) {
sector = disk.seek(iCylinder, iHead, iSector + 1, true);
if (!sector) {

View file

@ -574,7 +574,7 @@ RL11.prototype.bootSelectedDisk = function()
* a READY state is assured, and the readData() call shouldn't do anything to change that.
*/
this.cpu.setReset(0, true);
var err = this.readData(drive, 0, 0, 0, 512, 0);
var err = this.readData(drive, 0, 0, 0, 512, 0x0000);
if (err) {
this.notice("Unable to read the boot sector (" + err + ")");
}
@ -1023,7 +1023,7 @@ RL11.prototype.processCommand = function()
nWords = (0x10000 - this.regRLMP) & 0xffff;
addr = (((this.regRLBE & PDP11.RL11.RLBE.MASK)) << 16) | this.regRLBA; // 22 bit mode
if (this.messageEnabled()) this.printMessage(this.type + ": " + sFunc + "(" + iCylinder + ":" + iHead + ":" + iSector + ") @" + str.toOct(addr) + "-" + str.toOct(addr + ((nWords - 1) << 1)), true);
if (this.messageEnabled()) this.printMessage(this.type + ": " + sFunc + "(" + iCylinder + ":" + iHead + ":" + iSector + ") " + str.toOct(addr) + "-" + str.toOct(addr + ((nWords - 1) << 1)), true, true);
fInterrupt = fnReadWrite.call(this, drive, iCylinder, iHead, iSector, nWords, addr, this.endReadWrite.bind(this));
break;