Started work on new decoding functions

This commit is contained in:
Jeff 2016-09-22 18:47:32 -07:00 committed by Jeff Parsons
commit 7f0b6a091d
8 changed files with 852 additions and 732 deletions

View file

@ -1083,7 +1083,13 @@ CPUPDP11.prototype.runCPU = function(fUpdateFocus)
/*
* Execute the burst.
*/
this.stepCPU(nCyclesPerBurst);
try {
this.stepCPU(nCyclesPerBurst);
}
catch(exception) {
if (typeof exception != "number") throw exception;
if (DEBUG) this.println("CPU exception " + str.toHexWord(exception));
}
/*
* nCycles is how many cycles stepCPU() actually ran (nBurstCycles less any remaining nStepCycles).

View file

@ -40,85 +40,116 @@ if (NODE) {
}
/**
* op=0x00 (NOP)
* fnBIC(dst, src)
*
* @this {CPUStatePDP11}
* @param {number} src
* @param {number} dst
* @return {number} (~src & dst)
*/
PDP11.opNOP = function()
PDP11.fnBIC = function(src, dst)
{
this.nStepCycles -= 4;
return ~src & dst;
};
/*
* This 256-entry array of opcode functions is at the heart of the CPU engine: stepCPU(n).
/**
* op1170(opCode)
*
* It might be worth trying a switch() statement instead, to see how the performance compares,
* but I suspect that would vary quite a bit across JavaScript engines; for now, I'm putting my
* money on array lookup.
* @this {CPUStatePDP11}
* @param {number} opCode
*/
PDP11.aOpsPDP1170 = [
/* 0x00-0x03 */ PDP11.opNOP, PDP11.opNOP, PDP11.opNOP, PDP11.opNOP,
/* 0x04-0x07 */ PDP11.opNOP, PDP11.opNOP, PDP11.opNOP, PDP11.opNOP,
/* 0x08-0x0B */ PDP11.opNOP, PDP11.opNOP, PDP11.opNOP, PDP11.opNOP,
/* 0x0C-0x0F */ PDP11.opNOP, PDP11.opNOP, PDP11.opNOP, PDP11.opNOP,
/* 0x10-0x13 */ PDP11.opNOP, PDP11.opNOP, PDP11.opNOP, PDP11.opNOP,
/* 0x14-0x17 */ PDP11.opNOP, PDP11.opNOP, PDP11.opNOP, PDP11.opNOP,
/* 0x18-0x1B */ PDP11.opNOP, PDP11.opNOP, PDP11.opNOP, PDP11.opNOP,
/* 0x1C-0x1F */ PDP11.opNOP, PDP11.opNOP, PDP11.opNOP, PDP11.opNOP,
/* 0x20-0x23 */ PDP11.opNOP, PDP11.opNOP, PDP11.opNOP, PDP11.opNOP,
/* 0x24-0x27 */ PDP11.opNOP, PDP11.opNOP, PDP11.opNOP, PDP11.opNOP,
/* 0x28-0x2B */ PDP11.opNOP, PDP11.opNOP, PDP11.opNOP, PDP11.opNOP,
/* 0x2C-0x2F */ PDP11.opNOP, PDP11.opNOP, PDP11.opNOP, PDP11.opNOP,
/* 0x30-0x33 */ PDP11.opNOP, PDP11.opNOP, PDP11.opNOP, PDP11.opNOP,
/* 0x34-0x37 */ PDP11.opNOP, PDP11.opNOP, PDP11.opNOP, PDP11.opNOP,
/* 0x38-0x3B */ PDP11.opNOP, PDP11.opNOP, PDP11.opNOP, PDP11.opNOP,
/* 0x3C-0x3F */ PDP11.opNOP, PDP11.opNOP, PDP11.opNOP, PDP11.opNOP,
/* 0x40-0x43 */ PDP11.opNOP, PDP11.opNOP, PDP11.opNOP, PDP11.opNOP,
/* 0x44-0x47 */ PDP11.opNOP, PDP11.opNOP, PDP11.opNOP, PDP11.opNOP,
/* 0x48-0x4B */ PDP11.opNOP, PDP11.opNOP, PDP11.opNOP, PDP11.opNOP,
/* 0x4C-0x4F */ PDP11.opNOP, PDP11.opNOP, PDP11.opNOP, PDP11.opNOP,
/* 0x50-0x53 */ PDP11.opNOP, PDP11.opNOP, PDP11.opNOP, PDP11.opNOP,
/* 0x54-0x57 */ PDP11.opNOP, PDP11.opNOP, PDP11.opNOP, PDP11.opNOP,
/* 0x58-0x5B */ PDP11.opNOP, PDP11.opNOP, PDP11.opNOP, PDP11.opNOP,
/* 0x5C-0x5F */ PDP11.opNOP, PDP11.opNOP, PDP11.opNOP, PDP11.opNOP,
/* 0x60-0x63 */ PDP11.opNOP, PDP11.opNOP, PDP11.opNOP, PDP11.opNOP,
/* 0x64-0x67 */ PDP11.opNOP, PDP11.opNOP, PDP11.opNOP, PDP11.opNOP,
/* 0x68-0x6B */ PDP11.opNOP, PDP11.opNOP, PDP11.opNOP, PDP11.opNOP,
/* 0x6C-0x6F */ PDP11.opNOP, PDP11.opNOP, PDP11.opNOP, PDP11.opNOP,
/* 0x70-0x73 */ PDP11.opNOP, PDP11.opNOP, PDP11.opNOP, PDP11.opNOP,
/* 0x74-0x77 */ PDP11.opNOP, PDP11.opNOP, PDP11.opNOP, PDP11.opNOP,
/* 0x78-0x7B */ PDP11.opNOP, PDP11.opNOP, PDP11.opNOP, PDP11.opNOP,
/* 0x7C-0x7F */ PDP11.opNOP, PDP11.opNOP, PDP11.opNOP, PDP11.opNOP,
/* 0x80-0x83 */ PDP11.opNOP, PDP11.opNOP, PDP11.opNOP, PDP11.opNOP,
/* 0x84-0x87 */ PDP11.opNOP, PDP11.opNOP, PDP11.opNOP, PDP11.opNOP,
/* 0x88-0x8B */ PDP11.opNOP, PDP11.opNOP, PDP11.opNOP, PDP11.opNOP,
/* 0x8C-0x8F */ PDP11.opNOP, PDP11.opNOP, PDP11.opNOP, PDP11.opNOP,
/* 0x90-0x93 */ PDP11.opNOP, PDP11.opNOP, PDP11.opNOP, PDP11.opNOP,
/* 0x94-0x97 */ PDP11.opNOP, PDP11.opNOP, PDP11.opNOP, PDP11.opNOP,
/* 0x98-0x9B */ PDP11.opNOP, PDP11.opNOP, PDP11.opNOP, PDP11.opNOP,
/* 0x9C-0x9F */ PDP11.opNOP, PDP11.opNOP, PDP11.opNOP, PDP11.opNOP,
/* 0xA0-0xA3 */ PDP11.opNOP, PDP11.opNOP, PDP11.opNOP, PDP11.opNOP,
/* 0xA4-0xA7 */ PDP11.opNOP, PDP11.opNOP, PDP11.opNOP, PDP11.opNOP,
/* 0xA8-0xAB */ PDP11.opNOP, PDP11.opNOP, PDP11.opNOP, PDP11.opNOP,
/* 0xAC-0xAF */ PDP11.opNOP, PDP11.opNOP, PDP11.opNOP, PDP11.opNOP,
/* 0xB0-0xB3 */ PDP11.opNOP, PDP11.opNOP, PDP11.opNOP, PDP11.opNOP,
/* 0xB4-0xB7 */ PDP11.opNOP, PDP11.opNOP, PDP11.opNOP, PDP11.opNOP,
/* 0xB8-0xBB */ PDP11.opNOP, PDP11.opNOP, PDP11.opNOP, PDP11.opNOP,
/* 0xBC-0xBF */ PDP11.opNOP, PDP11.opNOP, PDP11.opNOP, PDP11.opNOP,
/* 0xC0-0xC3 */ PDP11.opNOP, PDP11.opNOP, PDP11.opNOP, PDP11.opNOP,
/* 0xC4-0xC7 */ PDP11.opNOP, PDP11.opNOP, PDP11.opNOP, PDP11.opNOP,
/* 0xC8-0xCB */ PDP11.opNOP, PDP11.opNOP, PDP11.opNOP, PDP11.opNOP,
/* 0xCC-0xCF */ PDP11.opNOP, PDP11.opNOP, PDP11.opNOP, PDP11.opNOP,
/* 0xD0-0xD3 */ PDP11.opNOP, PDP11.opNOP, PDP11.opNOP, PDP11.opNOP,
/* 0xD4-0xD7 */ PDP11.opNOP, PDP11.opNOP, PDP11.opNOP, PDP11.opNOP,
/* 0xD8-0xDB */ PDP11.opNOP, PDP11.opNOP, PDP11.opNOP, PDP11.opNOP,
/* 0xDC-0xDF */ PDP11.opNOP, PDP11.opNOP, PDP11.opNOP, PDP11.opNOP,
/* 0xE0-0xE3 */ PDP11.opNOP, PDP11.opNOP, PDP11.opNOP, PDP11.opNOP,
/* 0xE4-0xE7 */ PDP11.opNOP, PDP11.opNOP, PDP11.opNOP, PDP11.opNOP,
/* 0xE8-0xEB */ PDP11.opNOP, PDP11.opNOP, PDP11.opNOP, PDP11.opNOP,
/* 0xEC-0xEF */ PDP11.opNOP, PDP11.opNOP, PDP11.opNOP, PDP11.opNOP,
/* 0xF0-0xF3 */ PDP11.opNOP, PDP11.opNOP, PDP11.opNOP, PDP11.opNOP,
/* 0xF4-0xF7 */ PDP11.opNOP, PDP11.opNOP, PDP11.opNOP, PDP11.opNOP,
/* 0xF8-0xFB */ PDP11.opNOP, PDP11.opNOP, PDP11.opNOP, PDP11.opNOP,
/* 0xFC-0xFF */ PDP11.opNOP, PDP11.opNOP, PDP11.opNOP, PDP11.opNOP
PDP11.op1170 = function(opCode)
{
PDP11.aOpsF000_1170[opCode >> 12].call(this, opCode);
};
/**
* op0XXX_1170(opCode)
*
* @this {CPUStatePDP11}
* @param {number} opCode
*/
PDP11.op0XXX_1170 = function(opCode)
{
// PDP11.aOpsF000_1170[opCode >> 12].call(this, opCode);
};
/**
* opMOV(opCode)
*
* @this {CPUStatePDP11}
* @param {number} opCode
*/
PDP11.opMOV = function(opCode)
{
this.updateNZFlags(this.writeWordByMode(opCode, this.readWordByMode(opCode >> PDP11.SRCMODE.SHIFT)));
this.nStepCycles -= 1;
};
/**
* opCMP(opCode)
*
* @this {CPUStatePDP11}
* @param {number} opCode
*/
PDP11.opCMP = function(opCode)
{
var src = this.readWordByMode(opCode >> PDP11.SRCMODE.SHIFT);
var dst = this.readWordByMode(opCode);
var result = src - dst;
this.updateAllFlags(result, src, dst);
this.nStepCycles -= 1;
};
/**
* opBIT(opCode)
*
* @this {CPUStatePDP11}
* @param {number} opCode
*/
PDP11.opBIT = function(opCode)
{
this.updateNZFlags(this.readWordByMode(opCode >> PDP11.SRCMODE.SHIFT) & this.readWordByMode(opCode));
this.nStepCycles -= 1;
};
/**
* opBIC(opCode)
*
* @this {CPUStatePDP11}
* @param {number} opCode
*/
PDP11.opBIC = function(opCode)
{
this.updateNZFlags(this.updateWordByMode(opCode, this.readWordByMode(opCode >> PDP11.SRCMODE.SHIFT), PDP11.fnBIC));
this.nStepCycles -= 1;
};
/**
* opNOP(opCode)
*
* @this {CPUStatePDP11}
* @param {number} opCode
*/
PDP11.opNOP = function(opCode)
{
this.nStepCycles -= 1;
};
PDP11.aOpsF000_1170 = [
PDP11.op0XXX_1170,
PDP11.opMOV, // MOV 01SSDD
PDP11.opCMP, // CMP 02SSDD
PDP11.opBIT, // BIT 03SSDD
PDP11.opBIC, // BIC 04SSDD
PDP11.opNOP, // 0x5XXX
PDP11.opNOP, // 0x6XXX
PDP11.opNOP, // 0x7XXX
PDP11.opNOP, // 0x8XXX
PDP11.opNOP, // 0x9XXX
PDP11.opNOP, // 0xAXXX
PDP11.opNOP, // 0xBXXX
PDP11.opNOP, // 0xCXXX
PDP11.opNOP, // 0xDXXX
PDP11.opNOP, // 0xEXXX
PDP11.opNOP // 0xFXXX
];

View file

@ -92,17 +92,11 @@ Component.subclass(CPUStatePDP11, CPUPDP11);
/**
* initProcessor()
*
* Interestingly, if I dynamically generate aOps as an array of functions bound to "this", using the bind()
* method, overall performance is worse. You would think that eliminating the need to use the call() method
* on every opcode function invocation would be helpful, but it's not. I'm not sure exactly why yet; perhaps
* a Closure Compiler optimization is defeated when generating the function array at run-time instead of at
* compile-time.
*
* @this {CPUStatePDP11}
*/
CPUStatePDP11.prototype.initProcessor = function()
{
this.aOps = PDP11.aOpsPDP1170;
this.decode = PDP11.op1170.bind(this);
this.initRegs();
this.flags.complete = this.flags.debugCheck = false;
};
@ -133,10 +127,10 @@ CPUStatePDP11.prototype.initRegs = function()
*/
this.flagC = 0x10000; // PSW C bit
this.flagV = 0x8000; // PSW V bit
this.flagZ = 0xffff; // ~ PSW Z bit (TODO: Why is Z clear instead of set like all other flags?)
this.flagZ = 0xffff; // ~ PSW Z bit (TODO: Why is Z clear instead of set like all other flags?)
this.flagN = 0x8000; // PSW N bit
this.PSW = 0xf; // PSW other bits
this.regPSW = 0xf; // PSW other bits (TODO: What's the point of setting the flag bits here, too?)
this.regOp = -1; // current opcode
this.regsGen = [ // General R0 - R7
0, 0, 0, 0, 0, 0, 0, this.resetAddr
];
@ -153,7 +147,7 @@ CPUStatePDP11.prototype.initRegs = function()
this.loopRate = 9999; // instructions we can execute in 12ms
this.priorityReview = 2; // flag to mark if we need to check priority change
this.stackLimit = 0xff;
this.trapMask = 0;
this.opFlags = 0;
this.trapPSW = -1;
this.CPU_Error = 0;
this.cpuType = 70;
@ -637,6 +631,36 @@ CPUStatePDP11.prototype.setPSW = function(newPSW)
this.PSW = newPSW;
};
/**
* updateNZFlags(result)
*
* @this {CPUStatePDP11}
* @param {number} result
*/
CPUStatePDP11.prototype.updateNZFlags = function(result)
{
if (!this.opFlags & PDP11.OPFLAG.SKIP_FLAGS) {
this.flagN = this.flagZ = result;
this.flagV = 0;
}
};
/**
* updateAllFlags(result, src, dst)
*
* @this {CPUStatePDP11}
* @param {number} result
* @param {number} src
* @param {number} dst
*/
CPUStatePDP11.prototype.updateAllFlags = function(result, src, dst)
{
if (!this.opFlags & PDP11.OPFLAG.SKIP_FLAGS) {
this.flagN = this.flagZ = this.flagC = result;
this.flagV = (src ^ dst) & (src ^ result);
}
};
/**
* panic(reason)
*
@ -655,13 +679,11 @@ CPUStatePDP11.prototype.panic = function(reason)
*
* trap() handles all the trap/abort functions. It reads the trap vector from kernel
* D space, changes mode to reflect the new PSW and PC, and then pushes the old PSW and
* PC onto the new mode stack. trap() returns a -1 which is passed up through function
* calls to indicate that a trap/abort has occurred (suspend instruction processing).
* PC onto the new mode stack.
*
* @this {CPUStatePDP11}
* @param {number} vector
* @param {number} reason
* @return {number}
*/
CPUStatePDP11.prototype.trap = function(vector, reason)
{
@ -692,9 +714,9 @@ CPUStatePDP11.prototype.trap = function(vector, reason)
}
}
}
this.trapMask = 0; // lose interest in traps after an abort
this.trapPSW = -1; // reset flag that we have a trap within a trap
return -1; // signal that a trap has occurred
this.opFlags &= ~PDP11.OPFLAG.TRAP_MASK; // lose interest in traps after an abort
this.trapPSW = -1; // reset flag that we have a trap within a trap
throw vector | (reason << 8);
};
/**
@ -778,7 +800,7 @@ CPUStatePDP11.prototype.mapVirtualToPhysical = function(virtualAddress, accessMa
} else { // no max_memory check in 16 bit mode
if ((physicalAddress & 1) && !(accessMask & PDP11.BYTE_MODE)) {
this.CPU_Error |= 0x40;
return this.trap(4, 22);
this.trap(PDP11.TRAP.BUS_ERROR, 22);
}
}
return physicalAddress;
@ -787,22 +809,22 @@ CPUStatePDP11.prototype.mapVirtualToPhysical = function(virtualAddress, accessMa
page = (virtualAddress >> 13) & this.mmuMask[this.mmuMode];
pdr = this.mmuMap[this.mmuMode][page];
physicalAddress = ((this.mmuMap[this.mmuMode][page + 16] << 6) + (virtualAddress & 0x1fff)) & 0x3fffff;
if (this.MMR3 & 0x10) { // if 22 bit MM mode
if (this.MMR3 & 0x10) { // if 22 bit MM mode
if (physicalAddress >= BusPDP11.IOPAGE_UNIBUS && physicalAddress < BusPDP11.IOPAGE_22BIT) {
physicalAddress = this.mapUnibus(physicalAddress & 0x3ffff); // 18bit unibus space
}
} else {
physicalAddress &= 0x3ffff; // truncate if only 18 bit mapping
physicalAddress &= 0x3ffff; // truncate if only 18 bit mapping
if (physicalAddress >= BusPDP11.IOPAGE_18BIT) physicalAddress |= BusPDP11.IOPAGE_22BIT;
}
if (physicalAddress < BusPDP11.IOPAGE_UNIBUS) {
if (physicalAddress >= BusPDP11.MAX_MEMORY) {
this.CPU_Error |= 0x20;
return this.trap(4, 24); // KB11-EM does this after ABORT handling - KB11-CM before
this.trap(PDP11.TRAP.BUS_ERROR, 24); // KB11-EM does this after ABORT handling - KB11-CM before
}
if ((physicalAddress & 1) && !(accessMask & PDP11.BYTE_MODE)) {
this.CPU_Error |= 0x40;
return this.trap(4, 26);
this.trap(PDP11.TRAP.BUS_ERROR, 26);
}
}
switch (pdr & 0x7) {
@ -856,14 +878,14 @@ CPUStatePDP11.prototype.mapVirtualToPhysical = function(virtualAddress, accessMa
if (!(this.MMR0 & 0xe000)) {
this.MMR0 |= errorMask | (this.mmuLastMode << 5) | (this.mmuLastPage << 1);
}
return this.trap(0xa8, 28); // 0250
this.trap(PDP11.TRAP.MMU_FAULT, 28);
}
if (!(this.MMR0 & 0xf000)) {
//if (physicalAddress < 017772200 || physicalAddress > 017777677) {
if (physicalAddress < 0x3ff480 || physicalAddress > 0x3fffbf) {
this.MMR0 |= 0x1000; // MMU trap flag
if (this.MMR0 & 0x0200) {
this.trapMask |= 2; // MMU trap
this.opFlags |= PDP11.OPFLAG.TRAP_MMU;
}
}
}
@ -1015,10 +1037,11 @@ CPUStatePDP11.prototype.pushWord = function(data)
if (virtualAddress <= this.stackLimit - 32) {
this.CPU_Error |= 4; // Red stack
this.regsGen[6] = 4;
return this.trap(4, 32);
this.trap(PDP11.TRAP.BUS_ERROR, 32);
} else {
this.CPU_Error |= 8; // Yellow
this.opFlags |= 4;
}
this.CPU_Error |= 8; // Yellow
this.trapMask |= 4;
}
if ((physicalAddress = this.mapVirtualToPhysical(virtualAddress | 0x10000, PDP11.WRITE_MODE)) >= 0) {
return this.writeWordByAddr(physicalAddress, data);
@ -1059,22 +1082,27 @@ CPUStatePDP11.prototype.pushWord = function(data)
CPUStatePDP11.prototype.getVirtualByMode = function(addressMode, accessMode)
{
var virtualAddress, stepSize, reg = addressMode & 7;
switch ((addressMode >> 3) & 7) {
case 0: // Mode 0: Registers don't have a virtual address so trap!
return this.trap(4, 34); // trap for invalid virtual address
case 1: // Mode 1: (R)
case 0: // Mode 0: Registers don't have a virtual address so trap!
this.trap(PDP11.TRAP.BUS_ERROR, 34); // trap for invalid virtual address
break;
case 1: // Mode 1: (R)
if (reg === 6 && (!this.mmuMode) && (accessMode & PDP11.WRITE_MODE) &&
(this.regsGen[6] <= this.stackLimit || this.regsGen[6] >= 0xfffe)) {
if (this.regsGen[6] <= this.stackLimit - 32 || this.regsGen[6] >= 0xfffe) {
this.CPU_Error |= 4; // Red stack
this.regsGen[6] = 4;
return this.trap(4, 36);
this.trap(PDP11.TRAP.BUS_ERROR, 36);
} else {
this.CPU_Error |= 8; // Yellow
this.opFlags |= PDP11.OPFLAG.TRAP_SP;
}
this.CPU_Error |= 8; // Yellow
this.trapMask |= 4;
}
return (reg === 7 ? this.regsGen[reg] : (this.regsGen[reg] | 0x10000));
case 2: // Mode 2: (R)+
case 2: // Mode 2: (R)+
stepSize = 2;
virtualAddress = this.regsGen[reg];
if (reg !== 7) {
@ -1150,10 +1178,11 @@ CPUStatePDP11.prototype.getVirtualByMode = function(addressMode, accessMode)
if (this.regsGen[6] <= this.stackLimit - 32) {
this.CPU_Error |= 4; // Red stack
this.regsGen[6] = 4;
return this.trap(4, 38);
this.trap(PDP11.TRAP.BUS_ERROR, 38);
} else {
this.CPU_Error |= 8; // Yellow
this.opFlags |= PDP11.OPFLAG.TRAP_SP;
}
this.CPU_Error |= 8; // Yellow
this.trapMask |= 4;
}
return virtualAddress;
};
@ -1189,15 +1218,11 @@ CPUStatePDP11.prototype.getAddrByMode = function(addressMode, accessMode)
CPUStatePDP11.prototype.readWordByMode = function(addressMode)
{
var result;
if (!(addressMode & 0x38)) {
result = this.regsGen[addressMode & 7];
//LOG_SOURCE(result);
if (!(addressMode & PDP11.OPMODE.MASK)) {
result = this.regsGen[addressMode & PDP11.OPREG.MASK];
} else {
if ((result = this.getAddrByMode(addressMode, PDP11.READ_MODE)) >= 0) {
if ((result = this.readWordByAddr(result)) >= 0) {
//LOG_SOURCE(result);
}
}
var addr = this.getAddrByMode(addressMode, PDP11.READ_MODE);
result = this.readWordByAddr(addr);
}
return result;
};
@ -1225,6 +1250,46 @@ CPUStatePDP11.prototype.readByteByMode = function(addressMode)
return result;
};
/**
* writeWordByMode(addressMode, data)
*
* @this {CPUStatePDP11}
* @param {number} addressMode
* @param {number} data
* @return {number}
*/
CPUStatePDP11.prototype.writeWordByMode = function(addressMode, data)
{
if (!(addressMode & PDP11.OPMODE.MASK)) {
this.regsGen[addressMode & PDP11.OPREG.MASK] = data;
} else {
this.writeWordByAddr(this.getAddrByMode(addressMode, PDP11.WRITE_MODE), data);
}
return data;
};
/**
* updateWordByMode(addressMode, src, fnOp)
*
* @this {CPUStatePDP11}
* @param {number} addressMode
* @param {number} src
* @param {function(number,number)} fnOp
* @return {number}
*/
CPUStatePDP11.prototype.updateWordByMode = function(addressMode, src, fnOp)
{
var data;
if (!(addressMode & PDP11.OPMODE.MASK)) {
var reg = addressMode & PDP11.OPREG.MASK;
this.regsGen[reg] = data = fnOp(src, this.regsGen[reg]);
} else {
var addr = this.getAddrByMode(addressMode, PDP11.WRITE_MODE);
this.writeWordByAddr(addr, data = fnOp(src, this.readWordByAddr(addr)));
}
return data;
};
/**
* branch(PC, instruction)
*
@ -1315,6 +1380,28 @@ CPUStatePDP11.prototype.stepCPU = function(nMinCycles)
result,
virtualAddress, savePSW, reg, i, j;
/*
* Check for any pending traps.
*
* I've moved this TRAP_MASK check BEFORE we decode the next instruction instead
* of immediately AFTER, because the last instruction may have thrown an exception,
* kicking us out before we reach the bottom of this loop.
*/
if (this.opFlags & PDP11.OPFLAG.TRAP_MASK) {
if (this.opFlags & PDP11.OPFLAG.TRAP_MMU) {
this.trap(PDP11.TRAP.MMU_FAULT, 52); // MMU trap has priority
} else {
if (this.opFlags & PDP11.OPFLAG.TRAP_SP) {
this.trap(PDP11.TRAP.BUS_ERROR, 54); // then SP trap
} else {
if (this.opFlags & PDP11.OPFLAG.TRAP_TF) {
this.trap(PDP11.TRAP.BREAKPOINT, 56); // and finally a TF trap
}
}
}
this.opFlags &= ~PDP11.OPFLAG.TRAP_MASK;
}
if (this.priorityReview) { // if nothing has changed don't check priority
if (this.priorityReview === 1) {
this.priorityReview = 2; // SPL delay
@ -1347,7 +1434,7 @@ CPUStatePDP11.prototype.stepCPU = function(nMinCycles)
}
if (savePSW > (this.PSW & 0xe0)) {
if (j < 0) {
this.trap(0xA0, /*0240*/ 42);
this.trap(PDP11.TRAP.PIRQ, 42);
} else {
this.trap(this.interruptQueue[j].vector, 44);
this.interruptQueue.splice(j, 1);
@ -1355,69 +1442,81 @@ CPUStatePDP11.prototype.stepCPU = function(nMinCycles)
}
}
}
if (!(this.MMR0 & 0xe000)) {
this.MMR1 = 0;
this.MMR2 = this.regsGen[7];
}
// If needed T-bit trap at the end of this instruction
this.trapMask = this.PSW & 0x10;
if ((instruction = this.readWordByVirtual(this.regsGen[7])) >= 0) {
/*
* Snapshot the TF bit in opFlags, while simultaneously clearing all other opFlags;
* we'll check the TRAP_TF bit in opFlags when we come back around for another opcode.
*/
this.opFlags = this.PSW & PDP11.PSW.TF;
this.regOp = this.readWordByVirtual(this.regsGen[7]);
this.regsGen[7] = (this.regsGen[7] + 2) & 0xffff;
this.decode(this.regOp);
if (this.regOp >= 0) {
instruction = this.regOp;
this.regsGen[7] = (this.regsGen[7] + 2) & 0xffff;
switch (instruction & 0xF000) /*0170000*/ { // Double operand instructions xxSSDD
case 0x1000: /*0010000*/ // MOV 01SSDD
//LOG_INSTRUCTION(instruction, 2, "MOV");
if ((src = this.readWordByMode(instruction >> 6)) >= 0) {
if (!(instruction & 0x38)) {
this.regsGen[instruction & 7] = src;
this.flagN = this.flagZ = src;
this.flagV = 0;
} else {
if ((dstAddr = this.getAddrByMode(instruction, PDP11.WRITE_MODE)) >= 0) {
if (this.writeWordByAddr(dstAddr, src) >= 0) {
this.flagN = this.flagZ = src;
this.flagV = 0;
}
}
}
}
break;
case 0x2000: /*0020000*/ // CMP 02SSDD
//LOG_INSTRUCTION(instruction, 2, "CMP");
if ((src = this.readWordByMode(instruction >> 6)) >= 0) {
if ((dst = this.readWordByMode(instruction)) >= 0) {
result = src - dst;
this.flagN = this.flagZ = this.flagC = result;
this.flagV = (src ^ dst) & (src ^ result);
}
}
break;
case 0x3000: /*0030000*/ // BIT 03SSDD
//LOG_INSTRUCTION(instruction, 2, "BIT");
if ((src = this.readWordByMode(instruction >> 6)) >= 0) {
if ((dst = this.readWordByMode(instruction)) >= 0) {
this.flagN = this.flagZ = src & dst;
this.flagV = 0;
}
}
break;
case 0x4000: /*0040000*/ // BIC 04SSDD
//LOG_INSTRUCTION(instruction, 2, "BIC");
if ((src = this.readWordByMode(instruction >> 6)) >= 0) {
if (!(instruction & 0x38)) {
result = this.regsGen[instruction & 7] &= ~src;
this.flagN = this.flagZ = result;
this.flagV = 0;
} else {
if ((dst = this.readWordByAddr(dstAddr = this.getAddrByMode(instruction, PDP11.MODIFY_WORD))) >= 0) {
result = dst & ~src;
if (this.writeWordByAddr(dstAddr, result) >= 0) {
this.flagN = this.flagZ = result;
this.flagV = 0;
}
}
}
}
break;
// case 0x1000: /*0010000*/ // MOV 01SSDD
// //LOG_INSTRUCTION(instruction, 2, "MOV");
// if ((src = this.readWordByMode(instruction >> 6)) >= 0) {
// if (!(instruction & 0x38)) {
// this.regsGen[instruction & 7] = src;
// this.flagN = this.flagZ = src;
// this.flagV = 0;
// } else {
// if ((dstAddr = this.getAddrByMode(instruction, PDP11.WRITE_MODE)) >= 0) {
// if (this.writeWordByAddr(dstAddr, src) >= 0) {
// this.flagN = this.flagZ = src;
// this.flagV = 0;
// }
// }
// }
// }
// break;
// case 0x2000: /*0020000*/ // CMP 02SSDD
// //LOG_INSTRUCTION(instruction, 2, "CMP");
// if ((src = this.readWordByMode(instruction >> 6)) >= 0) {
// if ((dst = this.readWordByMode(instruction)) >= 0) {
// result = src - dst;
// this.flagN = this.flagZ = this.flagC = result;
// this.flagV = (src ^ dst) & (src ^ result);
// }
// }
// break;
// case 0x3000: /*0030000*/ // BIT 03SSDD
// //LOG_INSTRUCTION(instruction, 2, "BIT");
// if ((src = this.readWordByMode(instruction >> 6)) >= 0) {
// if ((dst = this.readWordByMode(instruction)) >= 0) {
// this.flagN = this.flagZ = src & dst;
// this.flagV = 0;
// }
// }
// break;
// case 0x4000: /*0040000*/ // BIC 04SSDD
// //LOG_INSTRUCTION(instruction, 2, "BIC");
// if ((src = this.readWordByMode(instruction >> 6)) >= 0) {
// if (!(instruction & 0x38)) {
// result = this.regsGen[instruction & 7] &= ~src;
// this.flagN = this.flagZ = result;
// this.flagV = 0;
// } else {
// if ((dst = this.readWordByAddr(dstAddr = this.getAddrByMode(instruction, PDP11.MODIFY_WORD))) >= 0) {
// result = dst & ~src;
// if (this.writeWordByAddr(dstAddr, result) >= 0) {
// this.flagN = this.flagZ = result;
// this.flagV = 0;
// }
// }
// }
// }
// break;
case 0x5000: /*0050000*/ // BIS 05SSDD
//LOG_INSTRUCTION(instruction, 2, "BIS");
if ((src = this.readWordByMode(instruction >> 6)) >= 0) {
@ -1753,11 +1852,11 @@ CPUStatePDP11.prototype.stepCPU = function(nMinCycles)
break;
case 0x8800: /*0104000*/ // EMT 104000 -> 104377
//LOG_INSTRUCTION(instruction, 7, "EMT");
this.trap(0x18, /*030*/ 2);
this.trap(PDP11.TRAP.EMULATOR, /*030*/ 2);
break;
case 0x8900: /*0104400*/ // TRAP 104400 -> 104777
//LOG_INSTRUCTION(instruction, 7, "TRAP");
this.trap(0x1C, /*034*/ 4);
this.trap(PDP11.TRAP.TRAP, /*034*/ 4);
break;
default:
switch (instruction & 0xFFC0) /*0177700*/ { // Single operand instructions xxxxDD
@ -2296,7 +2395,7 @@ CPUStatePDP11.prototype.stepCPU = function(nMinCycles)
//LOG_INSTRUCTION(instruction, 0, "HALT");
if (0xc000 & this.PSW) {
this.CPU_Error |= 0x80; /*0200*/
this.trap(4, 46);
this.trap(PDP11.TRAP.BUS_ERROR, 46);
} else {
this.runState = 3; // halt
this.endBurst();
@ -2320,11 +2419,11 @@ CPUStatePDP11.prototype.stepCPU = function(nMinCycles)
break;
case 0x3: /*0000003*/ // BPT 000003
//LOG_INSTRUCTION(instruction, 0, "BPT");
this.trap(0xC, /*014*/ 6);
this.trap(PDP11.TRAP.BREAKPOINT, /*014*/ 6);
break;
case 0x4: /*0000004*/ // IOT 000004
//LOG_INSTRUCTION(instruction, 0, "IOT");
this.trap(0x10, /*020*/ 8);
this.trap(PDP11.TRAP.IOT, /*020*/ 8);
break;
case 0x5: /*0000005*/ // RESET 000005
//LOG_INSTRUCTION(instruction, 0, "RESET");
@ -2343,14 +2442,16 @@ CPUStatePDP11.prototype.stepCPU = function(nMinCycles)
if ((savePSW = this.readWordByVirtual(dstAddr | 0x10000)) >= 0) {
this.regsGen[6] = (dstAddr + 2) & 0xffff;
savePSW &= 0xf8ff;
if (this.PSW & 0xc000) { // user / super restrictions
if (this.PSW & 0xc000) { // user / super restrictions
// keep SPL and allow lower only for modes and register set
savePSW = (savePSW & 0xf81f) | (this.PSW & 0xf8e0);
}
this.regsGen[7] = virtualAddress;
this.setPSW(savePSW);
this.trapMask &= ~0x10; // turn off Trace trap
if (instruction === 2) this.trapMask |= this.PSW & 0x10; // RTI enables immediate trace
this.opFlags &= ~PDP11.OPFLAG.TRAP_TF;
if (instruction === 2) { // RTI enables immediate trace
this.opFlags |= (this.PSW & PDP11.PSW.TF);
}
}
}
break;
@ -2360,7 +2461,7 @@ CPUStatePDP11.prototype.stepCPU = function(nMinCycles)
// break; // Exists on pdp 11/44 & KB11-EM
default: // We don't know this instruction
//LOG_INSTRUCTION(instruction, 11, "-unknown-");
this.trap(0x8, /*010*/ 48); // Illegal instruction
this.trap(PDP11.TRAP.RESERVED, /*010*/ 48); // reserved instruction
break;
}
}
@ -2369,18 +2470,6 @@ CPUStatePDP11.prototype.stepCPU = function(nMinCycles)
}
}
}
if (this.trapMask) { // check for any traps pending
if (this.trapMask & 2) {
this.trap(0xA8, /*0250*/ 52); // MMU trap has priority
} else {
if (this.trapMask & 4) {
this.trap(4, 54); // then SP trap
} else {
if (this.trapMask & 0x10) this.trap(0xC, /*014*/ 56); // and finally a T-bit trap
}
}
this.trapMask = 0;
}
} while (this.nStepCycles > 0);
}

View file

@ -214,7 +214,7 @@ if (DEBUGGER) {
};
/*
* CPU opcode ordinals
* CPU opcode IDs
*/
DebuggerPDP11.OPS = {
NONE: 0, ADC: 1, ADCB: 2, ADD: 3, ASL: 4, ASLB: 5, ASR: 6, ASRB: 7,
@ -261,120 +261,119 @@ if (DEBUGGER) {
DebuggerPDP11.REG_PSW = 20;
/*
* Operand descriptor masks; anything that's not covered by TYPE_SRC or TYPE_DST must be a TYPE_OTHER value.
* Operand type masks; anything that's not covered by OP_SRC or OP_DST must be a OP_OTHER value.
*/
DebuggerPDP11.TYPE_DSTREG = 0x0007;
DebuggerPDP11.TYPE_DSTMODE = 0x0038;
DebuggerPDP11.TYPE_DSTMODE_SHIFT = 3;
DebuggerPDP11.TYPE_DST = (DebuggerPDP11.TYPE_DSTMODE | DebuggerPDP11.TYPE_DSTREG);
DebuggerPDP11.TYPE_SRCREG = 0x01C0;
DebuggerPDP11.TYPE_SRCMODE = 0x0E00;
DebuggerPDP11.TYPE_SRC = (DebuggerPDP11.TYPE_SRCMODE | DebuggerPDP11.TYPE_SRCREG);
DebuggerPDP11.TYPE_BRANCH = 0x1000;
DebuggerPDP11.TYPE_DSTOFF = 0x2000;
DebuggerPDP11.TYPE_DSTNUM3 = 0x3000; // DST 3-bit number (ie, just the DSTREG field)
DebuggerPDP11.TYPE_DSTNUM6 = 0x6000; // DST 6-bit number (ie, both the DSTREG and DSTMODE fields)
DebuggerPDP11.TYPE_OTHER = 0xF000;
DebuggerPDP11.OP_DSTREG = PDP11.OPREG.MASK;
DebuggerPDP11.OP_DSTMODE = PDP11.OPMODE.MASK;
DebuggerPDP11.OP_DST = (DebuggerPDP11.OP_DSTMODE | DebuggerPDP11.OP_DSTREG);
DebuggerPDP11.OP_SRCREG = PDP11.OPREG.MASK << 6;
DebuggerPDP11.OP_SRCMODE = PDP11.OPMODE.MASK << 6;
DebuggerPDP11.OP_SRC = (DebuggerPDP11.OP_SRCMODE | DebuggerPDP11.OP_SRCREG);
DebuggerPDP11.OP_BRANCH = 0x1000;
DebuggerPDP11.OP_DSTOFF = 0x2000;
DebuggerPDP11.OP_DSTNUM3 = 0x3000; // DST 3-bit number (ie, just the DSTREG field)
DebuggerPDP11.OP_DSTNUM6 = 0x6000; // DST 6-bit number (ie, both the DSTREG and DSTMODE fields)
DebuggerPDP11.OP_OTHER = 0xF000;
/*
* The opMasks table contains opcode masks, and each mask refers to table of possible values, and each
* The opTable contains opcode masks, and each mask refers to table of possible values, and each
* value refers to an array that contains:
*
* [0]: {number} of the opcode name (see OP.*)
* [1]: {number} containing the first operand descriptor bit(s), if any
* [2]: {number} containing the second operand descriptor bit(s), if any
* [1]: {number} containing the first operand type bit(s), if any
* [2]: {number} containing the second operand type bit(s), if any
*
* Note that, by convention, opcodes that require two operands list the SRC operand first and DST operand
* second (ie, the OPPOSITE of the Intel convention).
*
* Also note that, for some of the newer PDP-11 opcodes (eg, MUL, DIV, ASH, ASHC), the location of the
* opcode's SRC and DST bits are reversed. This is why, for example, you'll see the MUL instruction defined
* below as having TYPE_DST for the first operand and TYPE_SRCREG for the second operand. This does NOT mean
* below as having OP_DST for the first operand and OP_SRCREG for the second operand. This does NOT mean
* that the opcode's destination operand is being listed first, but rather that the bits describing the source
* operand are in the opcode's TYPE_DST field.
* operand are in the opcode's OP_DST field.
*/
DebuggerPDP11.opMasks = {
DebuggerPDP11.opTable = {
0xF000: {
0x1000: [DebuggerPDP11.OPS.MOV, DebuggerPDP11.TYPE_SRC, DebuggerPDP11.TYPE_DST], // 01SSDD
0x2000: [DebuggerPDP11.OPS.CMP, DebuggerPDP11.TYPE_SRC, DebuggerPDP11.TYPE_DST], // 02SSDD
0x3000: [DebuggerPDP11.OPS.BIT, DebuggerPDP11.TYPE_SRC, DebuggerPDP11.TYPE_DST], // 03SSDD
0x4000: [DebuggerPDP11.OPS.BIC, DebuggerPDP11.TYPE_SRC, DebuggerPDP11.TYPE_DST], // 04SSDD
0x5000: [DebuggerPDP11.OPS.BIS, DebuggerPDP11.TYPE_SRC, DebuggerPDP11.TYPE_DST], // 05SSDD
0x6000: [DebuggerPDP11.OPS.ADD, DebuggerPDP11.TYPE_SRC, DebuggerPDP11.TYPE_DST], // 06SSDD
0x9000: [DebuggerPDP11.OPS.MOVB, DebuggerPDP11.TYPE_SRC, DebuggerPDP11.TYPE_DST], // 11SSDD
0xA000: [DebuggerPDP11.OPS.CMPB, DebuggerPDP11.TYPE_SRC, DebuggerPDP11.TYPE_DST], // 12SSDD
0xB000: [DebuggerPDP11.OPS.BITB, DebuggerPDP11.TYPE_SRC, DebuggerPDP11.TYPE_DST], // 13SSDD
0xC000: [DebuggerPDP11.OPS.BICB, DebuggerPDP11.TYPE_SRC, DebuggerPDP11.TYPE_DST], // 14SSDD
0xD000: [DebuggerPDP11.OPS.BISB, DebuggerPDP11.TYPE_SRC, DebuggerPDP11.TYPE_DST], // 15SSDD
0xE000: [DebuggerPDP11.OPS.SUB, DebuggerPDP11.TYPE_SRC, DebuggerPDP11.TYPE_DST] // 16SSDD
0x1000: [DebuggerPDP11.OPS.MOV, DebuggerPDP11.OP_SRC, DebuggerPDP11.OP_DST], // 01SSDD
0x2000: [DebuggerPDP11.OPS.CMP, DebuggerPDP11.OP_SRC, DebuggerPDP11.OP_DST], // 02SSDD
0x3000: [DebuggerPDP11.OPS.BIT, DebuggerPDP11.OP_SRC, DebuggerPDP11.OP_DST], // 03SSDD
0x4000: [DebuggerPDP11.OPS.BIC, DebuggerPDP11.OP_SRC, DebuggerPDP11.OP_DST], // 04SSDD
0x5000: [DebuggerPDP11.OPS.BIS, DebuggerPDP11.OP_SRC, DebuggerPDP11.OP_DST], // 05SSDD
0x6000: [DebuggerPDP11.OPS.ADD, DebuggerPDP11.OP_SRC, DebuggerPDP11.OP_DST], // 06SSDD
0x9000: [DebuggerPDP11.OPS.MOVB, DebuggerPDP11.OP_SRC, DebuggerPDP11.OP_DST], // 11SSDD
0xA000: [DebuggerPDP11.OPS.CMPB, DebuggerPDP11.OP_SRC, DebuggerPDP11.OP_DST], // 12SSDD
0xB000: [DebuggerPDP11.OPS.BITB, DebuggerPDP11.OP_SRC, DebuggerPDP11.OP_DST], // 13SSDD
0xC000: [DebuggerPDP11.OPS.BICB, DebuggerPDP11.OP_SRC, DebuggerPDP11.OP_DST], // 14SSDD
0xD000: [DebuggerPDP11.OPS.BISB, DebuggerPDP11.OP_SRC, DebuggerPDP11.OP_DST], // 15SSDD
0xE000: [DebuggerPDP11.OPS.SUB, DebuggerPDP11.OP_SRC, DebuggerPDP11.OP_DST] // 16SSDD
},
0xFE00: {
0x0800: [DebuggerPDP11.OPS.JSR, DebuggerPDP11.TYPE_SRCREG, DebuggerPDP11.TYPE_DST], // 004RDD
0x7000: [DebuggerPDP11.OPS.MUL, DebuggerPDP11.TYPE_DST, DebuggerPDP11.TYPE_SRCREG], // 070RSS
0x7200: [DebuggerPDP11.OPS.DIV, DebuggerPDP11.TYPE_DST, DebuggerPDP11.TYPE_SRCREG], // 071RSS
0x7400: [DebuggerPDP11.OPS.ASH, DebuggerPDP11.TYPE_DST, DebuggerPDP11.TYPE_SRCREG], // 072RSS
0x7600: [DebuggerPDP11.OPS.ASHC, DebuggerPDP11.TYPE_DST, DebuggerPDP11.TYPE_SRCREG], // 073RSS
0x7800: [DebuggerPDP11.OPS.XOR, DebuggerPDP11.TYPE_SRCREG, DebuggerPDP11.TYPE_DST], // 074RSS
0x7E00: [DebuggerPDP11.OPS.SOB, DebuggerPDP11.TYPE_SRCREG, DebuggerPDP11.TYPE_DSTOFF] // 077Rnn
0x0800: [DebuggerPDP11.OPS.JSR, DebuggerPDP11.OP_SRCREG, DebuggerPDP11.OP_DST], // 004RDD
0x7000: [DebuggerPDP11.OPS.MUL, DebuggerPDP11.OP_DST, DebuggerPDP11.OP_SRCREG], // 070RSS
0x7200: [DebuggerPDP11.OPS.DIV, DebuggerPDP11.OP_DST, DebuggerPDP11.OP_SRCREG], // 071RSS
0x7400: [DebuggerPDP11.OPS.ASH, DebuggerPDP11.OP_DST, DebuggerPDP11.OP_SRCREG], // 072RSS
0x7600: [DebuggerPDP11.OPS.ASHC, DebuggerPDP11.OP_DST, DebuggerPDP11.OP_SRCREG], // 073RSS
0x7800: [DebuggerPDP11.OPS.XOR, DebuggerPDP11.OP_SRCREG, DebuggerPDP11.OP_DST], // 074RSS
0x7E00: [DebuggerPDP11.OPS.SOB, DebuggerPDP11.OP_SRCREG, DebuggerPDP11.OP_DSTOFF] // 077Rnn
},
0xFF00: {
0x0100: [DebuggerPDP11.OPS.BR, DebuggerPDP11.TYPE_BRANCH],
0x0200: [DebuggerPDP11.OPS.BNE, DebuggerPDP11.TYPE_BRANCH],
0x0300: [DebuggerPDP11.OPS.BEQ, DebuggerPDP11.TYPE_BRANCH],
0x0400: [DebuggerPDP11.OPS.BGE, DebuggerPDP11.TYPE_BRANCH],
0x0500: [DebuggerPDP11.OPS.BLT, DebuggerPDP11.TYPE_BRANCH],
0x0600: [DebuggerPDP11.OPS.BGT, DebuggerPDP11.TYPE_BRANCH],
0x0700: [DebuggerPDP11.OPS.BLE, DebuggerPDP11.TYPE_BRANCH],
0x8000: [DebuggerPDP11.OPS.BPL, DebuggerPDP11.TYPE_BRANCH],
0x8100: [DebuggerPDP11.OPS.BMI, DebuggerPDP11.TYPE_BRANCH],
0x8200: [DebuggerPDP11.OPS.BHI, DebuggerPDP11.TYPE_BRANCH],
0x8300: [DebuggerPDP11.OPS.BLOS, DebuggerPDP11.TYPE_BRANCH],
0x8400: [DebuggerPDP11.OPS.BVC, DebuggerPDP11.TYPE_BRANCH],
0x8500: [DebuggerPDP11.OPS.BVS, DebuggerPDP11.TYPE_BRANCH],
0x8600: [DebuggerPDP11.OPS.BCC, DebuggerPDP11.TYPE_BRANCH],
0x8700: [DebuggerPDP11.OPS.BCS, DebuggerPDP11.TYPE_BRANCH],
0x0100: [DebuggerPDP11.OPS.BR, DebuggerPDP11.OP_BRANCH],
0x0200: [DebuggerPDP11.OPS.BNE, DebuggerPDP11.OP_BRANCH],
0x0300: [DebuggerPDP11.OPS.BEQ, DebuggerPDP11.OP_BRANCH],
0x0400: [DebuggerPDP11.OPS.BGE, DebuggerPDP11.OP_BRANCH],
0x0500: [DebuggerPDP11.OPS.BLT, DebuggerPDP11.OP_BRANCH],
0x0600: [DebuggerPDP11.OPS.BGT, DebuggerPDP11.OP_BRANCH],
0x0700: [DebuggerPDP11.OPS.BLE, DebuggerPDP11.OP_BRANCH],
0x8000: [DebuggerPDP11.OPS.BPL, DebuggerPDP11.OP_BRANCH],
0x8100: [DebuggerPDP11.OPS.BMI, DebuggerPDP11.OP_BRANCH],
0x8200: [DebuggerPDP11.OPS.BHI, DebuggerPDP11.OP_BRANCH],
0x8300: [DebuggerPDP11.OPS.BLOS, DebuggerPDP11.OP_BRANCH],
0x8400: [DebuggerPDP11.OPS.BVC, DebuggerPDP11.OP_BRANCH],
0x8500: [DebuggerPDP11.OPS.BVS, DebuggerPDP11.OP_BRANCH],
0x8600: [DebuggerPDP11.OPS.BCC, DebuggerPDP11.OP_BRANCH],
0x8700: [DebuggerPDP11.OPS.BCS, DebuggerPDP11.OP_BRANCH],
0x8800: [DebuggerPDP11.OPS.EMT], // 104000..104377
0x8900: [DebuggerPDP11.OPS.TRAP] // 104400..104777
},
0xFFC0: {
0x0040: [DebuggerPDP11.OPS.JMP, DebuggerPDP11.TYPE_DST], // 0001DD
0x00C0: [DebuggerPDP11.OPS.SWAB, DebuggerPDP11.TYPE_DST], // 0003DD
0x0A00: [DebuggerPDP11.OPS.CLR, DebuggerPDP11.TYPE_DST], // 0050DD
0x0A40: [DebuggerPDP11.OPS.COM, DebuggerPDP11.TYPE_DST], // 0051DD
0x0A80: [DebuggerPDP11.OPS.INC, DebuggerPDP11.TYPE_DST], // 0052DD
0x0AC0: [DebuggerPDP11.OPS.DEC, DebuggerPDP11.TYPE_DST], // 0053DD
0x0B00: [DebuggerPDP11.OPS.NEG, DebuggerPDP11.TYPE_DST], // 0054DD
0x0B40: [DebuggerPDP11.OPS.ADC, DebuggerPDP11.TYPE_DST], // 0055DD
0x0B80: [DebuggerPDP11.OPS.SBC, DebuggerPDP11.TYPE_DST], // 0056DD
0x0BC0: [DebuggerPDP11.OPS.TST, DebuggerPDP11.TYPE_DST], // 0057DD
0x0C00: [DebuggerPDP11.OPS.ROR, DebuggerPDP11.TYPE_DST], // 0060DD
0x0C40: [DebuggerPDP11.OPS.ROL, DebuggerPDP11.TYPE_DST], // 0061DD
0x0C80: [DebuggerPDP11.OPS.ASR, DebuggerPDP11.TYPE_DST], // 0062DD
0x0CC0: [DebuggerPDP11.OPS.ASL, DebuggerPDP11.TYPE_DST], // 0063DD
0x0D00: [DebuggerPDP11.OPS.MARK, DebuggerPDP11.TYPE_DSTNUM6], // 0064nn
0x0D40: [DebuggerPDP11.OPS.MFPI, DebuggerPDP11.TYPE_DST], // 0065SS
0x0D80: [DebuggerPDP11.OPS.MTPI, DebuggerPDP11.TYPE_DST], // 0066DD
0x0DC0: [DebuggerPDP11.OPS.SXT, DebuggerPDP11.TYPE_DST], // 0067DD
0x8A00: [DebuggerPDP11.OPS.CLRB, DebuggerPDP11.TYPE_DST], // 1050DD
0x8A40: [DebuggerPDP11.OPS.COMB, DebuggerPDP11.TYPE_DST], // 1051DD
0x8A80: [DebuggerPDP11.OPS.INCB, DebuggerPDP11.TYPE_DST], // 1052DD
0x8AC0: [DebuggerPDP11.OPS.DECB, DebuggerPDP11.TYPE_DST], // 1053DD
0x8B00: [DebuggerPDP11.OPS.NEGB, DebuggerPDP11.TYPE_DST], // 1054DD
0x8B40: [DebuggerPDP11.OPS.ADCB, DebuggerPDP11.TYPE_DST], // 1055DD
0x8B80: [DebuggerPDP11.OPS.SBCB, DebuggerPDP11.TYPE_DST], // 1056DD
0x8BC0: [DebuggerPDP11.OPS.TSTB, DebuggerPDP11.TYPE_DST], // 1057DD
0x8C00: [DebuggerPDP11.OPS.RORB, DebuggerPDP11.TYPE_DST], // 1060DD
0x8C40: [DebuggerPDP11.OPS.ROLB, DebuggerPDP11.TYPE_DST], // 1061DD
0x8C80: [DebuggerPDP11.OPS.ASRB, DebuggerPDP11.TYPE_DST], // 1062DD
0x8CC0: [DebuggerPDP11.OPS.ASLB, DebuggerPDP11.TYPE_DST], // 1063DD
0x8D00: [DebuggerPDP11.OPS.MTPS, DebuggerPDP11.TYPE_DST], // 1064SS (only on LSI-11)
0x8D40: [DebuggerPDP11.OPS.MFPD, DebuggerPDP11.TYPE_DST], // 1065DD (same as MFPI if no separate instruction/data spaces)
0x8D80: [DebuggerPDP11.OPS.MTPD, DebuggerPDP11.TYPE_DST], // 1066DD (same as MTPI if no separate instruction/data spaces)
0x8DC0: [DebuggerPDP11.OPS.MFPS, DebuggerPDP11.TYPE_DST] // 1067SS (only on LSI-11)
0x0040: [DebuggerPDP11.OPS.JMP, DebuggerPDP11.OP_DST], // 0001DD
0x00C0: [DebuggerPDP11.OPS.SWAB, DebuggerPDP11.OP_DST], // 0003DD
0x0A00: [DebuggerPDP11.OPS.CLR, DebuggerPDP11.OP_DST], // 0050DD
0x0A40: [DebuggerPDP11.OPS.COM, DebuggerPDP11.OP_DST], // 0051DD
0x0A80: [DebuggerPDP11.OPS.INC, DebuggerPDP11.OP_DST], // 0052DD
0x0AC0: [DebuggerPDP11.OPS.DEC, DebuggerPDP11.OP_DST], // 0053DD
0x0B00: [DebuggerPDP11.OPS.NEG, DebuggerPDP11.OP_DST], // 0054DD
0x0B40: [DebuggerPDP11.OPS.ADC, DebuggerPDP11.OP_DST], // 0055DD
0x0B80: [DebuggerPDP11.OPS.SBC, DebuggerPDP11.OP_DST], // 0056DD
0x0BC0: [DebuggerPDP11.OPS.TST, DebuggerPDP11.OP_DST], // 0057DD
0x0C00: [DebuggerPDP11.OPS.ROR, DebuggerPDP11.OP_DST], // 0060DD
0x0C40: [DebuggerPDP11.OPS.ROL, DebuggerPDP11.OP_DST], // 0061DD
0x0C80: [DebuggerPDP11.OPS.ASR, DebuggerPDP11.OP_DST], // 0062DD
0x0CC0: [DebuggerPDP11.OPS.ASL, DebuggerPDP11.OP_DST], // 0063DD
0x0D00: [DebuggerPDP11.OPS.MARK, DebuggerPDP11.OP_DSTNUM6], // 0064nn
0x0D40: [DebuggerPDP11.OPS.MFPI, DebuggerPDP11.OP_DST], // 0065SS
0x0D80: [DebuggerPDP11.OPS.MTPI, DebuggerPDP11.OP_DST], // 0066DD
0x0DC0: [DebuggerPDP11.OPS.SXT, DebuggerPDP11.OP_DST], // 0067DD
0x8A00: [DebuggerPDP11.OPS.CLRB, DebuggerPDP11.OP_DST], // 1050DD
0x8A40: [DebuggerPDP11.OPS.COMB, DebuggerPDP11.OP_DST], // 1051DD
0x8A80: [DebuggerPDP11.OPS.INCB, DebuggerPDP11.OP_DST], // 1052DD
0x8AC0: [DebuggerPDP11.OPS.DECB, DebuggerPDP11.OP_DST], // 1053DD
0x8B00: [DebuggerPDP11.OPS.NEGB, DebuggerPDP11.OP_DST], // 1054DD
0x8B40: [DebuggerPDP11.OPS.ADCB, DebuggerPDP11.OP_DST], // 1055DD
0x8B80: [DebuggerPDP11.OPS.SBCB, DebuggerPDP11.OP_DST], // 1056DD
0x8BC0: [DebuggerPDP11.OPS.TSTB, DebuggerPDP11.OP_DST], // 1057DD
0x8C00: [DebuggerPDP11.OPS.RORB, DebuggerPDP11.OP_DST], // 1060DD
0x8C40: [DebuggerPDP11.OPS.ROLB, DebuggerPDP11.OP_DST], // 1061DD
0x8C80: [DebuggerPDP11.OPS.ASRB, DebuggerPDP11.OP_DST], // 1062DD
0x8CC0: [DebuggerPDP11.OPS.ASLB, DebuggerPDP11.OP_DST], // 1063DD
0x8D00: [DebuggerPDP11.OPS.MTPS, DebuggerPDP11.OP_DST], // 1064SS (only on LSI-11)
0x8D40: [DebuggerPDP11.OPS.MFPD, DebuggerPDP11.OP_DST], // 1065DD (same as MFPI if no separate instruction/data spaces)
0x8D80: [DebuggerPDP11.OPS.MTPD, DebuggerPDP11.OP_DST], // 1066DD (same as MTPI if no separate instruction/data spaces)
0x8DC0: [DebuggerPDP11.OPS.MFPS, DebuggerPDP11.OP_DST] // 1067SS (only on LSI-11)
},
0xFFF8: {
0x0080: [DebuggerPDP11.OPS.RTS, DebuggerPDP11.TYPE_DSTREG], // 00020R
0x0098: [DebuggerPDP11.OPS.SPL, DebuggerPDP11.TYPE_DSTNUM3] // 00023N
0x0080: [DebuggerPDP11.OPS.RTS, DebuggerPDP11.OP_DSTREG], // 00020R
0x0098: [DebuggerPDP11.OPS.SPL, DebuggerPDP11.OP_DSTNUM3] // 00023N
},
0xFFFF: {
0x0000: [DebuggerPDP11.OPS.HALT], // 000000
@ -443,7 +442,7 @@ if (DEBUGGER) {
var sMessages = cmp.getMachineParm('messages');
if (sMessages) this.messageInit(sMessages);
this.opMasks = DebuggerPDP11.opMasks;
this.opTable = DebuggerPDP11.opTable;
this.messageDump(MessagesPDP11.BUS, function onDumpBus(asArgs) { dbg.dumpBus(asArgs); });
@ -1594,9 +1593,8 @@ if (DEBUGGER) {
}
this.aBreakWrite = ["bw"];
/*
* nSuppressBreaks ensures we can't get into an infinite loop where a breakpoint lookup requires
* reading a segment descriptor via getSegment(), and that triggers more memory reads, which triggers
* more breakpoint checks.
* nSuppressBreaks ensures we can't get into an infinite loop where a breakpoint lookup
* requires reading memory that triggers more memory reads, which triggers more breakpoint checks.
*/
this.nSuppressBreaks = 0;
};
@ -1892,10 +1890,9 @@ if (DEBUGGER) {
var opCode = this.getWord(dbgAddr, true);
var opDesc;
for (var mask in this.opMasks) {
var opMask = this.opMasks[mask];
var bits = opCode & mask;
opDesc = opMask[bits];
for (var mask in this.opTable) {
var opMasks = this.opTable[mask];
opDesc = opMasks[opCode & mask];
if (opDesc) break;
}
@ -1907,10 +1904,10 @@ if (DEBUGGER) {
for (var iOperand = 1; iOperand <= cOperands; iOperand++) {
var type = opDesc[iOperand];
if (type === undefined) continue;
var opType = opDesc[iOperand];
if (opType === undefined) continue;
var sOperand = this.getOperand(opCode, type, dbgAddr);
var sOperand = this.getOperand(opCode, opType, dbgAddr);
if (!sOperand || !sOperand.length) {
sOperands = "INVALID";
@ -1956,63 +1953,63 @@ if (DEBUGGER) {
};
/**
* getOperand(opCode, type, dbgAddr)
* getOperand(opCode, opType, dbgAddr)
*
* If getOperand() returns an Array rather than a string, then the first element is the original
* operand, and the second element is a comment containing an alternate representation of the operand.
*
* @this {DebuggerPDP11}
* @param {number} opCode
* @param {number} type
* @param {number} opType
* @param {DbgAddrPDP11} dbgAddr
* @return {string|Array.<string>}
*/
DebuggerPDP11.prototype.getOperand = function(opCode, type, dbgAddr)
DebuggerPDP11.prototype.getOperand = function(opCode, opType, dbgAddr)
{
var sOperand = "", disp, addr;
/*
* Take care of TYPE_OTHER opcodes first; then all we'll have to worry about
* next are TYPE_SRC or TYPE_DST opcodes.
* Take care of OP_OTHER opcodes first; then all we'll have to worry about
* next are OP_SRC or OP_DST opcodes.
*/
var typeOther = type & DebuggerPDP11.TYPE_OTHER;
if (typeOther == DebuggerPDP11.TYPE_BRANCH) {
var opTypeOther = opType & DebuggerPDP11.OP_OTHER;
if (opTypeOther == DebuggerPDP11.OP_BRANCH) {
disp = ((opCode & 0xff) << 24) >> 23;
addr = (dbgAddr.addr + disp) & 0xffff;
sOperand = this.toStrBase(addr);
}
else if (typeOther == DebuggerPDP11.TYPE_DSTOFF) {
else if (opTypeOther == DebuggerPDP11.OP_DSTOFF) {
disp = (opCode & 0x3f) << 1;
addr = (dbgAddr.addr - disp) & 0xffff;
sOperand = this.toStrBase(addr);
}
else if (typeOther == DebuggerPDP11.TYPE_DSTNUM3) {
else if (opTypeOther == DebuggerPDP11.OP_DSTNUM3) {
disp = (opCode & 0x7);
sOperand = this.toStrBase(disp, 2);
}
else if (typeOther == DebuggerPDP11.TYPE_DSTNUM6) {
else if (opTypeOther == DebuggerPDP11.OP_DSTNUM6) {
disp = (opCode & 0x3f);
sOperand = this.toStrBase(disp);
}
else {
/*
* Isolate all TYPE_SRC or TYPE_DST bits from opcode in the mode variable.
* Isolate all OP_SRC or OP_DST bits from opcode in the opMode variable.
*/
var mode = opCode & type;
var opMode = opCode & opType;
/*
* Convert TYPE_SRC bits into TYPE_DST bits, since they use the same format.
* Convert OP_SRC bits into OP_DST bits, since they use the same format.
*/
if (type & DebuggerPDP11.TYPE_SRC) {
mode >>= 6;
type >>= 6;
if (opType & DebuggerPDP11.OP_SRC) {
opMode >>= 6;
opType >>= 6;
}
if (type & DebuggerPDP11.TYPE_DST) {
if (opType & DebuggerPDP11.OP_DST) {
var wIndex;
var reg = mode & DebuggerPDP11.TYPE_DSTREG;
var reg = opMode & DebuggerPDP11.OP_DSTREG;
/*
* Note that opcodes that specify only REG bits in the type mask (ie, no MOD bits)
* will automatically default to MODE_REG below.
* Note that opcodes that specify only REG bits in the opType mask (ie, no MOD bits)
* will automatically default to OPMODE_REG below.
*/
switch((mode & DebuggerPDP11.TYPE_DSTMODE) >> DebuggerPDP11.TYPE_DSTMODE_SHIFT) {
switch((opMode & DebuggerPDP11.OP_DSTMODE)) {
case PDP11.OPMODE.REG: // 0x0: REGISTER
sOperand = this.getRegName(reg);
break;

View file

@ -84,19 +84,19 @@ var TYPEDARRAYS = (typeof ArrayBuffer !== 'undefined');
* which all machine components should start using; eg: "if (PDP11.DEBUG) ..." instead of "if (DEBUG) ...".
*/
var PDP11 = {
APPCLASS: APPCLASS,
APPNAME: APPNAME,
APPVERSION: APPVERSION, // shared
BYTEARRAYS: BYTEARRAYS,
COMPILED: COMPILED, // shared
CSSCLASS: CSSCLASS, // shared
DEBUG: DEBUG, // shared
DEBUGGER: DEBUGGER,
MAXDEBUG: MAXDEBUG, // shared
PRIVATE: PRIVATE, // shared
TYPEDARRAYS: TYPEDARRAYS,
SITEHOST: SITEHOST, // shared
XMLVERSION: XMLVERSION, // shared
APPCLASS: APPCLASS,
APPNAME: APPNAME,
APPVERSION: APPVERSION, // shared
BYTEARRAYS: BYTEARRAYS,
COMPILED: COMPILED, // shared
CSSCLASS: CSSCLASS, // shared
DEBUG: DEBUG, // shared
DEBUGGER: DEBUGGER,
MAXDEBUG: MAXDEBUG, // shared
PRIVATE: PRIVATE, // shared
TYPEDARRAYS:TYPEDARRAYS,
SITEHOST: SITEHOST, // shared
XMLVERSION: XMLVERSION, // shared
/*
* CPU model numbers (supported)
@ -121,68 +121,95 @@ var PDP11 = {
* certain that this file is included BEFORE the first reference to any of these properties, that
* automatic inlining will no longer occur.
*/
ADDR_INVALID: -1,
ADDR_INVALID: -1,
/*
* Processor modes
*/
MODE: {
KERNEL: 0x0,
SUPER: 0x1,
UNUSED: 0x2,
USER: 0x3,
MASK: 0x3
KERNEL: 0x0,
SUPER: 0x1,
UNUSED: 0x2,
USER: 0x3,
MASK: 0x3
},
/*
* Processor Status flag definitions (stored in regPSW)
*/
PSW: {
CF: 0x0001, // bit 0: Carry Flag
CF_SHIFT: 0,
VF: 0x0002, // bit 1: Overflow Flag (aka OF on Intel processors)
VF_SHIFT: 1,
ZF: 0x0004, // bit 2: Zero Flag
ZF_SHIFT: 2,
NF: 0x0008, // bit 3: Negative Flag (aka SF -- Sign Flag -- on Intel processors)
NF_SHIFT: 3,
TF: 0x0010, // bit 4: Trap Flag
TF_SHIFT: 4,
PRI: 0x00E0, // bits 5-7: Priority
PRI_SHIFT: 5,
UNUSED: 0x0700, // bits 8-10: unused
REGSET: 0x0800, // bit 11: Register Set
PMODE: 0x3000, // bits 12-13: Prev Mode (see PDP11.MODE)
PMODE_SHIFT:12,
CMODE: 0xC000, // bits 14-15: Curr Mode (see PDP11.MODE)
CMODE_SHIFT:14
CF: 0x0001, // bit 0: Carry Flag
CF_SHIFT: 0,
VF: 0x0002, // bit 1: Overflow Flag (aka OF on Intel processors)
VF_SHIFT: 1,
ZF: 0x0004, // bit 2: Zero Flag
ZF_SHIFT: 2,
NF: 0x0008, // bit 3: Negative Flag (aka SF -- Sign Flag -- on Intel processors)
NF_SHIFT: 3,
TF: 0x0010, // bit 4: Trap Flag
TF_SHIFT: 4,
PRI: 0x00E0, // bits 5-7: Priority
PRI_SHIFT: 5,
UNUSED: 0x0700, // bits 8-10: unused
REGSET: 0x0800, // bit 11: Register Set
PMODE: 0x3000, // bits 12-13: Prev Mode (see PDP11.MODE)
PMODE_SHIFT: 12,
CMODE: 0xC000, // bits 14-15: Curr Mode (see PDP11.MODE)
CMODE_SHIFT: 14
},
/*
* Interrupt-related flags (stored in intFlags)
*/
INTFLAG: {
NONE: 0x0000,
INTR: 0x00ff, // mask for 8 bits, representing interrupt levels 0-7
HALT: 0x0100 // halt requested; see opHLT()
NONE: 0x0000,
INTR: 0x00ff, // mask for 8 bits, representing interrupt levels 0-7
HALT: 0x0100 // halt requested; see opHLT()
},
OPFLAG: {
TRAP_TF: 0x10, // aka PDP11.PSW.TF
TRAP_MMU: 0x20,
TRAP_SP: 0x40,
TRAP_MASK: 0x70,
SKIP_FLAGS: 0x80
},
/*
* Opcode modes
* Opcode reg (opcode bits 2-0)
*/
OPREG: {
MASK: 0x07
},
/*
* Opcode modes (opcode bits 5-3)
*/
OPMODE: {
REG: 0x0, // REGISTER (register is operand)
REGD: 0x1, // REGISTER DEFERRED (register is address of operand)
POSTINC: 0x2, // POST-INCREMENT (register is address of operand, register incremented)
POSTINCD: 0x3, // POST-INCREMENT DEFERRED (register is address of address of operand, register incremented)
PREDEC: 0x4, // PRE-DECREMENT (register decremented, register is address of operand)
PREDECD: 0x5, // PRE-DECREMENT DEFERRED (register decremented, register is address of address of operand)
INDEX: 0x6, // INDEX (register + next word is address of operand)
INDEXD: 0x7 // INDEX DEFERRED (register + next word is address of address of operand)
REG: 0x00, // REGISTER (register is operand)
REGD: 0x08, // REGISTER DEFERRED (register is address of operand)
POSTINC: 0x10, // POST-INCREMENT (register is address of operand, register incremented)
POSTINCD: 0x18, // POST-INCREMENT DEFERRED (register is address of address of operand, register incremented)
PREDEC: 0x20, // PRE-DECREMENT (register decremented, register is address of operand)
PREDECD: 0x28, // PRE-DECREMENT DEFERRED (register decremented, register is address of address of operand)
INDEX: 0x30, // INDEX (register + next word is address of operand)
INDEXD: 0x38, // INDEX DEFERRED (register + next word is address of address of operand)
MASK: 0x38
},
/*
* Opcode definitions
*/
OPCODE: {
// TODO
DSTMODE: {
MASK: 0x003F,
SHIFT: 0
},
SRCMODE: {
MASK: 0x0FC0,
SHIFT: 6
},
TRAP: {
UNDEFINED: 0x00, // 000 (reserved)
BUS_ERROR: 0x04, // 004 illegal instructions, bus errors, stack limit, illegal internal address, microbreak
RESERVED: 0x08, // 010 reserved instructions
BREAKPOINT: 0x0C, // 014 BPT, breakpoint trap (trace)
IOT: 0x10, // 020 IOT, input/output trap
POWER_FAIL: 0x14, // 024 power fail
EMULATOR: 0x18, // 030 EMT, emulator trap
TRAP: 0x1C, // 034 TRAP instruction
PIRQ: 0xA0, // 240 PIRQ, program interrupt request
MMU_FAULT: 0xA8 // 250 MMU aborts and traps
},
BYTE_MODE: 1,
READ_MODE: 2,
WRITE_MODE: 4,

View file

@ -222,17 +222,9 @@ DevicePDP11.prototype.readPSW = function(addr)
*/
DevicePDP11.prototype.writePSW = function(data, addr)
{
/*
* TODO: Determine whether we need to replicate the code in access_iopage() that returns a bogus
* error when writing to ADDR_PSW, as a way of preventing instructions like CLR from updating the flags
* and potentially modifying some of the PSW bits that were just set (eg, the Z flag).
*
* If so, then we'll need to centralize the flag update logic, so that it can be skipped whenever a
* special one-time opcode flag is set. Because there are a number of arithmetic instructions besides
* CLR that could be used to modify ADDR_PSW.
*/
var maskDisallowed = PDP11.PSW.UNUSED | PDP11.PSW.TF;
this.cpu.setPSW((data & ~maskDisallowed) | (this.cpu.getPSW() & maskDisallowed));
this.cpu.opFlags |= PDP11.OPFLAG.SKIP_FLAGS;
};
/**
@ -623,27 +615,6 @@ DevicePDP11.prototype.kw11_interrupt = function()
}
};
/**
* mapUnibus(unibusAddress)
*
* @this {DevicePDP11}
* @param {number} unibusAddress
* @return {number}
*/
DevicePDP11.prototype.mapUnibus = function(unibusAddress)
{
var idx = (unibusAddress >> 13) & 0x1f;
if (idx < 31) {
if (this.cpu.MMR3 & 0x20) {
unibusAddress = (this.cpu.unibusMap[idx] + (unibusAddress & 0x1ffe)) & 0x3ffffe;
if (unibusAddress >= BusPDP11.IOPAGE_UNIBUS && unibusAddress < BusPDP11.IOPAGE_22BIT) this.cpu.panic(898);
}
} else {
unibusAddress |= BusPDP11.IOPAGE_22BIT;
}
return unibusAddress;
};
/**
* getData(xhr, callback, meta, block, address, count)
*
@ -764,7 +735,7 @@ DevicePDP11.prototype.readData = function(meta, block, address, count)
return;
}
for (word = 0; word < meta.blocksize && count > 0; word++) {
if (this.cpu.writeWordByAddr((meta.mapped? this.mapUnibus(address) : address), meta.cache[block][word]) < 0) {
if (this.cpu.writeWordByAddr((meta.mapped? this.cpu.mapUnibus(address) : address), meta.cache[block][word]) < 0) {
meta.postProcess(2, meta, block, address, count); // NXM
return;
}
@ -798,7 +769,7 @@ DevicePDP11.prototype.writeData = function(meta, block, address, count)
}
}
for (word = 0; word < meta.blocksize && count > 0; word++) {
data = this.cpu.readWordByAddr((meta.mapped? this.mapUnibus(address) : address));
data = this.cpu.readWordByAddr((meta.mapped? this.cpu.mapUnibus(address) : address));
if (data < 0) {
meta.postProcess(2, meta, block, address, count); // NXM
return;