New improved PDP-10 processor flag handling

This commit is contained in:
Jeff 2017-03-04 21:07:56 -08:00 committed by Jeff Parsons
commit ffb7fa1221
6 changed files with 287 additions and 263 deletions

View file

@ -251,7 +251,7 @@ PDP10.opILDB = function(op, acc)
* We can implement this as a simple combination of opIBP() and opLDB(), but taking care that we only call
* opIBP() on phase 1.
*/
if (this.regPS < 0) {
if (this.regBP < 0) {
//noinspection JSUnresolvedFunction
PDP10.opIBP.call(this, op, acc);
}
@ -286,14 +286,14 @@ PDP10.opLDB = function(op, acc)
* is with regEA containing the address of the bits to be loaded.
*/
var w = this.readWord(this.regEA);
if (this.regPS < 0) {
this.regPS = w;
if (this.regBP < 0) {
this.regBP = w;
this.regRA = this.regEA | PDP10.OPCODE.I_BIT;
this.advancePC(-1);
return;
}
var p = (this.regPS / PDP10.OPCODE.P_SCALE) & PDP10.OPCODE.P_MASK;
var s = (this.regPS >> PDP10.OPCODE.S_SHIFT) & PDP10.OPCODE.S_MASK;
var p = (this.regBP / PDP10.OPCODE.P_SCALE) & PDP10.OPCODE.P_MASK;
var s = (this.regBP >> PDP10.OPCODE.S_SHIFT) & PDP10.OPCODE.S_MASK;
if (p + s <= 32) {
/*
* WARNING: When using JavaScript's 32-bit operators with values that could set bit 31 and produce a
@ -310,7 +310,7 @@ PDP10.opLDB = function(op, acc)
w = Math.trunc(w / Math.pow(2, p)) % Math.pow(2, s);
}
this.writeWord(acc, w);
this.regPS = -1;
this.regBP = -1;
};
/**
@ -341,7 +341,7 @@ PDP10.opIDPB = function(op, acc)
* We can implement this as a simple combination of opIBP() and opDDB(), but taking care that we only call
* opIBP() on phase 1.
*/
if (this.regPS < 0) {
if (this.regBP < 0) {
//noinspection JSUnresolvedFunction
PDP10.opIBP.call(this, op, acc);
}
@ -376,14 +376,14 @@ PDP10.opDPB = function(op, acc)
* is with regEA containing the address of the bits to be stored.
*/
var w = this.readWord(this.regEA);
if (this.regPS < 0) {
this.regPS = w;
if (this.regBP < 0) {
this.regBP = w;
this.regRA = this.regEA | PDP10.OPCODE.I_BIT;
this.advancePC(-1);
return;
}
var p = (this.regPS / PDP10.OPCODE.P_SCALE) & PDP10.OPCODE.P_MASK;
var s = (this.regPS >> PDP10.OPCODE.S_SHIFT) & PDP10.OPCODE.S_MASK;
var p = (this.regBP / PDP10.OPCODE.P_SCALE) & PDP10.OPCODE.P_MASK;
var s = (this.regBP >> PDP10.OPCODE.S_SHIFT) & PDP10.OPCODE.S_MASK;
/*
* Regarding the SPECIAL CONSIDERATIONS above, even if the P ("shift") and/or S ("mask") values are
* over-large, we "mask" the resulting byte value (b) to 36 bits, so that when we re-assemble the final
@ -392,7 +392,7 @@ PDP10.opDPB = function(op, acc)
var b = ((this.readWord(acc) % Math.pow(2, s)) * Math.pow(2, p)) % PDP10.WORD_LIMIT;
w = (w - (w % Math.pow(2, p + s))) + b + (w % Math.pow(2, p));
this.writeWord(this.regEA, w);
this.regPS = -1;
this.regBP = -1;
};
/**
@ -1436,14 +1436,14 @@ PDP10.opASH = function(op, acc)
* If all those bits in the original value (w) were 0s, then adding bitsShifted to it could NOT
* produce a value > MAX_POS36.
*/
if (w + bitsShifted > PDP10.MAX_POS36) this.fOverflow = true;
if (w + bitsShifted > PDP10.MAX_POS36) this.regPS |= PDP10.PSFLAG.OVFL;
} else {
/*
* Since w was negative, overflow occurs ONLY if any of the bits we shifted out were 0s.
* If all those bits in the original value (w) were 1s, subtracting bitsShifted from it could NOT
* produce a value <= MAX_POS36.
*/
if (w - bitsShifted <= PDP10.MAX_POS36) this.fOverflow = true;
if (w - bitsShifted <= PDP10.MAX_POS36) this.regPS |= PDP10.PSFLAG.OVFL;
}
} else {
if (s <= -35) {
@ -1848,7 +1848,7 @@ PDP10.opPUSH = function(op, acc)
p += 0o000001000001;
this.writeWord(p & PDP10.HALF_MASK, this.readWord(this.regEA));
if (p >= PDP10.WORD_LIMIT) p -= PDP10.WORD_LIMIT;
if (!((p / PDP10.HALF_SHIFT)|0)) this.fPDOverflow = true;
if (!((p / PDP10.HALF_SHIFT)|0)) this.regPS |= PDP10.PSFLAG.PD_OVFL;
} else {
/*
* This is the SIMH behavior, which appears to increment each half of AC independently.
@ -1858,7 +1858,7 @@ PDP10.opPUSH = function(op, acc)
p = (p + 0o000001000000) - (p & PDP10.HALF_MASK) + addr;
if (p >= PDP10.WORD_LIMIT) {
p -= PDP10.WORD_LIMIT;
this.fPDOverflow = true;
this.regPS |= PDP10.PSFLAG.PD_OVFL;
}
}
this.writeWord(acc, p);
@ -1888,7 +1888,7 @@ PDP10.opPOP = function(op, acc)
if (this.regEA == acc) p = src; // this avoids re-reading the accumulator if the write just overwrote it
p -= 0o000001000001;
if (p < 0) p += PDP10.WORD_LIMIT;
if (((p / PDP10.HALF_SHIFT)|0) == PDP10.HALF_MASK) this.fPDOverflow = true;
if (((p / PDP10.HALF_SHIFT)|0) == PDP10.HALF_MASK) this.regPS |= PDP10.PSFLAG.PD_OVFL;
this.writeWord(acc, p);
};

View file

@ -178,15 +178,14 @@ class CPUStatePDP10 extends CPUPDP10 {
this.regPC = this.lastPC = this.addrReset;
/*
* This next internal reg is used only with byte instructions, to record an active byte
* pointer state (regPS).
* This next internal reg is used only with byte instructions, to record an active byte pointer.
*/
this.regPS = -1;
this.regBP = -1;
/*
* Assorted processor flags
*/
this.fOverflow = this.fCarry0 = this.fCarry1 = this.fNoDivide = this.fPDOverflow = false;
this.regPS = 0;
/*
* This is queried and displayed by the Panel when it's not displaying its own ADDRESS register
@ -291,13 +290,9 @@ class CPUStatePDP10 extends CPUPDP10 {
this.regRA,
this.regOP,
this.regPC,
this.regBP,
this.regPS,
this.opFlags,
this.fOverflow,
this.fCarry0,
this.fCarry1,
this.fNoDivide,
this.fPDOverflow,
this.lastPC,
this.addrLast,
this.addrReset
@ -327,13 +322,9 @@ class CPUStatePDP10 extends CPUPDP10 {
this.regRA,
this.regOP,
this.regPC,
this.regBP,
this.regPS,
this.opFlags,
this.fOverflow,
this.fCarry0,
this.fCarry1,
this.fNoDivide,
this.fPDOverflow,
this.lastPC,
this.addrLast,
this.addrReset
@ -349,6 +340,19 @@ class CPUStatePDP10 extends CPUPDP10 {
return true;
}
/**
* getPS()
*
* Gets the processor state flags in the format required by various program control operations.
*
* @this {CPUStatePDP10}
* @return {number}
*/
getPS()
{
return this.regPS & PDP10.HALF_MASK;
}
/**
* readFlags()
*
@ -360,8 +364,8 @@ class CPUStatePDP10 extends CPUPDP10 {
readFlags()
{
var flags = 0;
if (this.fOverflow) flags |= PDP10.RFLAG.OVFL;
if (this.fPDOverflow) flags |= PDP10.RFLAG.PDOVFL;
if (this.regPS & PDP10.PSFLAG.OVFL) flags |= PDP10.RFLAG.OVFL;
if (this.regPS & PDP10.PSFLAG.PD_OVFL) flags |= PDP10.RFLAG.PD_OVFL;
return flags;
}
@ -375,8 +379,8 @@ class CPUStatePDP10 extends CPUPDP10 {
*/
writeFlags(w)
{
if (w & PDP10.WFLAG.OVFL_CL) this.fOverflow = false;
if (w & PDP10.WFLAG.PDOVFL_CL) this.fPDOverflow = false;
if (w & PDP10.WFLAG.OVFL_CL) this.regPS &= ~PDP10.PSFLAG.OVFL;
if (w & PDP10.WFLAG.PD_OVFL_CL) this.regPS &= ~PDP10.PSFLAG.PD_OVFL;
}
/**
@ -507,7 +511,7 @@ class CPUStatePDP10 extends CPUPDP10 {
if (src != PDP10.MIN_NEG36) {
src = PDP10.TWO_POW36 - src;
} else {
this.fOverflow = this.fCarry1 = true;
this.regPS |= (PDP10.PSFLAG.OVFL | PDP10.PSFLAG.CARRY1);
}
}
return src;
@ -525,7 +529,7 @@ class CPUStatePDP10 extends CPUPDP10 {
negate(src)
{
if (!src) {
this.fCarry0 = this.fCarry1 = true;
this.regPS |= (PDP10.PSFLAG.CARRY0 | PDP10.PSFLAG.CARRY1);
}
else {
/*
@ -533,7 +537,7 @@ class CPUStatePDP10 extends CPUPDP10 {
* the MIN_NEG36 case anyway, and since subtraction in that case doesn't alter src, we skip the subtraction.
*/
if (src == PDP10.MIN_NEG36) {
this.fOverflow = this.fCarry1 = true;
this.regPS |= (PDP10.PSFLAG.OVFL | PDP10.PSFLAG.CARRY1);
} else {
src = PDP10.TWO_POW36 - src;
}

View file

@ -240,6 +240,7 @@ class DebuggerPDP10 extends Debugger {
copyAddr(dbgAddr, dbgCopy)
{
dbgAddr.addr = dbgCopy.addr;
dbgAddr.fPhysical = dbgCopy.fPhysical;
dbgAddr.fTemporary = dbgCopy.fTemporary;
dbgAddr.nBase = dbgCopy.nBase;
return dbgAddr;
@ -277,7 +278,7 @@ class DebuggerPDP10 extends Debugger {
*/
packAddr(dbgAddr)
{
return [dbgAddr.addr, dbgAddr.fPhysical, dbgAddr.nBase, dbgAddr.fTemporary, dbgAddr.sCmd];
return [dbgAddr.addr, dbgAddr.fPhysical, dbgAddr.fTemporary, dbgAddr.nBase, dbgAddr.sCmd];
}
/**
@ -863,30 +864,31 @@ class DebuggerPDP10 extends Debugger {
getRegValue(iReg)
{
var value;
var cpu = this.cpu;
switch(iReg) {
case DebuggerPDP10.REGS.PC:
value = this.cpu.getPC();
value = cpu.getPC();
break;
case DebuggerPDP10.REGS.RA:
value = this.cpu.regRA;
value = cpu.regRA;
break;
case DebuggerPDP10.REGS.EA:
value = this.cpu.regEA;
value = cpu.regEA;
break;
case DebuggerPDP10.REGS.C0:
value = this.cpu.fCarry0? 1 : 0;
value = (cpu.regPS & PDP10.PSFLAG.CARRY0)? 1 : 0;
break;
case DebuggerPDP10.REGS.C1:
value = this.cpu.fCarry1? 1 : 0;
value = (cpu.regPS & PDP10.PSFLAG.CARRY1)? 1 : 0;
break;
case DebuggerPDP10.REGS.OV:
value = this.cpu.fOverflow? 1 : 0;
value = (cpu.regPS & PDP10.PSFLAG.OVFL)? 1 : 0;
break;
case DebuggerPDP10.REGS.ND:
value = this.cpu.fNoDivide? 1 : 0;
value = (cpu.regPS & PDP10.PSFLAG.NO_DIVIDE)? 1 : 0;
break;
case DebuggerPDP10.REGS.PD:
value = this.cpu.fPDOverflow? 1 : 0;
value = (cpu.regPS & PDP10.PSFLAG.PD_OVFL)? 1 : 0;
break;
}
return value;

View file

@ -190,7 +190,27 @@ var PDP10 = {
IRQ_MASK: 0x0003,
DEBUGGER: 0x0004, // set if the Debugger wants to perform checks
WAIT: 0x0008, // WAIT operation in progress
PRESERVE: 0x000F, // OPFLAG bits to preserve prior to the next instruction
PRESERVE: 0x000F // OPFLAG bits to preserve prior to the next instruction
},
/*
* Flags returned by getPS() for various program control operations.
*/
PSFLAG: {
OVFL: 0o400000, // Overflow
CARRY0: 0o200000, // Carry 0
CARRY1: 0o100000, // Carry 1
FP_OVFL: 0o040000, // Floating-Point Overflow
BYTE_INT: 0o020000, // Byte Interrupt
USER_MODE: 0o010000, // Processor is in User Mode
USER_IO: 0o004000, // User I/O
FP_UNFL: 0o000100, // Floating-Point Underflow
NO_DIVIDE: 0o000040, // No Divide
/*
* Only the low 18 bits (above) are returned by getPS(); the following (bits 18 to 31)
* are defined for internal use only.
*/
PD_OVFL: 0o1000000 // Pushdown Overflow
},
/*
@ -201,15 +221,15 @@ var PDP10 = {
OVFL: 0o000010, // Overflow
OVFL_IE: 0o000020, // Overflow Interrupt Enabled
TRAP_OFF: 0o000040, // Trap Offset
FPOVFL: 0o000100, // Floating-Point Overflow
FPOVFL_IE: 0o000200, // Floating-Point Overflow Interrupt Enabled
FP_OVFL: 0o000100, // Floating-Point Overflow
FP_OVFL_IE: 0o000200, // Floating-Point Overflow Interrupt Enabled
CLOCK: 0o001000, // Clock Flag
CLOCK_IE: 0o002000, // Clock Interrupt Enabled
NXM: 0o010000, // Non-Existent Memory
PRM: 0o020000, // Memory Protection
ADB: 0o040000, // Address Break
UIO: 0o100000, // User In-Out
PDOVFL: 0o200000 // Pushdown Overflow (TODO: Verify this is correct; the May 1968 doc may have a typo)
PD_OVFL: 0o200000 // Pushdown Overflow (TODO: Verify this is correct; the May 1968 doc may have a typo)
},
/*
@ -222,9 +242,9 @@ var PDP10 = {
OVFL_CL: 0o000010, // Clear Overflow
OVFL_IE: 0o000020, // Enable Overflow Interrupt
OVFL_ID: 0o000040, // Disable Overflow Interrupt
FPOVFL_CL: 0o000100, // Clear Floating-Point Overflow
FPOVFL_IE: 0o000200, // Enable Floating-Point Overflow Interrupt
FPOVFL_ID: 0o000400, // Disable Floating-Point Overflow Interrupt
FP_OVFL_CL: 0o000100, // Clear Floating-Point Overflow
FP_OVFL_IE: 0o000200, // Enable Floating-Point Overflow Interrupt
FP_OVFL_ID: 0o000400, // Disable Floating-Point Overflow Interrupt
CLOCK_CL: 0o001000, // Clear Clock Flag
CLOCK_IE: 0o002000, // Enable Clock Interrupt
CLOCK_ID: 0o004000, // Disable Clock Interrupt
@ -232,7 +252,7 @@ var PDP10 = {
PRM_CL: 0o020000, // Clear Memory Protection
ADB_CL: 0o040000, // Clear Address Break
UIO_CL: 0o200000, // Clear All In-Out Devices
PDOVFL_CL: 0o400000 // Clear Pushdown Overflow
PD_OVFL_CL: 0o400000 // Clear Pushdown Overflow
},
/*