Started work on new decoding functions
This commit is contained in:
parent
a13bb9348a
commit
7f0b6a091d
8 changed files with 852 additions and 732 deletions
|
|
@ -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).
|
||||
|
|
|
|||
|
|
@ -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
|
||||
];
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
Loading…
Reference in a new issue