Added initial logic for decoding PDP-10 input-output instructions
This commit is contained in:
parent
e04bec1af4
commit
1ac769431f
7 changed files with 431 additions and 287 deletions
|
|
@ -47,7 +47,9 @@ if (NODE) {
|
|||
PDP10.opKA10 = function(op)
|
||||
{
|
||||
/*
|
||||
* We shift op right 4 more bits, leaving only the 9 bits required for the table index.
|
||||
* We shift op right 4 more bits, leaving only the 9 bits required for the table index. Those
|
||||
* 4 bits are normally an accumulator index, which we also mask and pass along, since most instructions
|
||||
* will use an accumulator, and those that don't simply ignore it.
|
||||
*/
|
||||
PDP10.aOpXXX_KA10[op >> 4].call(this, op, op & PDP10.OPCODE.A_MASK);
|
||||
};
|
||||
|
|
@ -1362,9 +1364,9 @@ PDP10.opDIVB = function(op, acc)
|
|||
*
|
||||
* Arithmetic Shifting
|
||||
*
|
||||
* These two instructions produce an arithmetic shift right or left of the number in AC or the
|
||||
* double length number in accumulators A and A+1. Shifting is the movement of the contents of
|
||||
* a register bit-to-bit. The operation discussed here is similar to logical shifting [see §2.4
|
||||
* These two instructions [ASH, ASHC] produce an arithmetic shift right or left of the number in AC
|
||||
* or the double length number in accumulators A and A+1. Shifting is the movement of the contents
|
||||
* of a register bit-to-bit. The operation discussed here is similar to logical shifting [see §2.4
|
||||
* and the illustration on page 2-24], but in an arithmetic shift only the magnitude part is
|
||||
* shifted - the sign is unaffected. In a double length number the 70-bit string made up of the
|
||||
* magnitude parts of the two words is shifted, but the sign of the low order word is made equal
|
||||
|
|
@ -1560,7 +1562,7 @@ PDP10.opJFFO = function(op, acc)
|
|||
*
|
||||
* Concatenate the magnitude portions of accumulators A and A+1 with A on the left, and shift
|
||||
* the 70-bit combination in bits 1-35 and 37-71 the number of places specified by E. Do not shift
|
||||
* AC bit 0, but make bit 0 of AC A +1 equal to it if at least one shift occurs (ie if E is nonzero).
|
||||
* AC bit 0, but make bit 0 of AC A+1 equal to it if at least one shift occurs (ie if E is nonzero).
|
||||
*
|
||||
* If E is positive, shift left bringing 0s into bit 71 (bit 35 of AC A+1); bit 37 (bit 1 of AC A+1)
|
||||
* is shifted into bit 35; data shifted out of bit 1 is lost; set Overflow if any bit of significance
|
||||
|
|
@ -1584,7 +1586,7 @@ PDP10.opASHC = function(op, acc)
|
|||
*
|
||||
* Concatenate accumulators A and A+1 with A on the left, and rotate the 72-bit combination the
|
||||
* number of places specified by E. If E is positive, rotate left; bit 0 is rotated into bit 71
|
||||
* (bit 35 of AC A +1) and bit 36 into bit 35. If E is negative, rotate right; bit 35 is rotated
|
||||
* (bit 35 of AC A+1) and bit 36 into bit 35. If E is negative, rotate right; bit 35 is rotated
|
||||
* into bit 36 and bit 71 into bit 0.
|
||||
*
|
||||
* @this {CPUStatePDP10}
|
||||
|
|
@ -4835,9 +4837,9 @@ PDP10.opTSON = function(op, acc)
|
|||
*
|
||||
* @this {CPUStatePDP10}
|
||||
* @param {number} op
|
||||
* @param {number} acc
|
||||
* @param {number} dev
|
||||
*/
|
||||
PDP10.opBLKI = function(op, acc)
|
||||
PDP10.opBLKI = function(op, dev)
|
||||
{
|
||||
this.opUndefined(op);
|
||||
};
|
||||
|
|
@ -4847,9 +4849,9 @@ PDP10.opBLKI = function(op, acc)
|
|||
*
|
||||
* @this {CPUStatePDP10}
|
||||
* @param {number} op
|
||||
* @param {number} acc
|
||||
* @param {number} dev
|
||||
*/
|
||||
PDP10.opDATAI = function(op, acc)
|
||||
PDP10.opDATAI = function(op, dev)
|
||||
{
|
||||
this.opUndefined(op);
|
||||
};
|
||||
|
|
@ -4859,9 +4861,9 @@ PDP10.opDATAI = function(op, acc)
|
|||
*
|
||||
* @this {CPUStatePDP10}
|
||||
* @param {number} op
|
||||
* @param {number} acc
|
||||
* @param {number} dev
|
||||
*/
|
||||
PDP10.opBLKO = function(op, acc)
|
||||
PDP10.opBLKO = function(op, dev)
|
||||
{
|
||||
this.opUndefined(op);
|
||||
};
|
||||
|
|
@ -4871,9 +4873,9 @@ PDP10.opBLKO = function(op, acc)
|
|||
*
|
||||
* @this {CPUStatePDP10}
|
||||
* @param {number} op
|
||||
* @param {number} acc
|
||||
* @param {number} dev
|
||||
*/
|
||||
PDP10.opDATAO = function(op, acc)
|
||||
PDP10.opDATAO = function(op, dev)
|
||||
{
|
||||
this.opUndefined(op);
|
||||
};
|
||||
|
|
@ -4883,11 +4885,18 @@ PDP10.opDATAO = function(op, acc)
|
|||
*
|
||||
* @this {CPUStatePDP10}
|
||||
* @param {number} op
|
||||
* @param {number} acc
|
||||
* @param {number} dev
|
||||
*/
|
||||
PDP10.opCONO = function(op, acc)
|
||||
PDP10.opCONO = function(op, dev)
|
||||
{
|
||||
this.opUndefined(op);
|
||||
switch(dev) {
|
||||
case PDP10.DEVICES.APR:
|
||||
this.writeFlags(this.readWord(this.regEA));
|
||||
break;
|
||||
default:
|
||||
this.opUndefined(op);
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -4895,11 +4904,18 @@ PDP10.opCONO = function(op, acc)
|
|||
*
|
||||
* @this {CPUStatePDP10}
|
||||
* @param {number} op
|
||||
* @param {number} acc
|
||||
* @param {number} dev
|
||||
*/
|
||||
PDP10.opCONI = function(op, acc)
|
||||
PDP10.opCONI = function(op, dev)
|
||||
{
|
||||
this.opUndefined(op);
|
||||
switch(dev) {
|
||||
case PDP10.DEVICES.APR:
|
||||
this.writeWord(this.regEA, this.readFlags());
|
||||
break;
|
||||
default:
|
||||
this.opUndefined(op);
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -4907,9 +4923,9 @@ PDP10.opCONI = function(op, acc)
|
|||
*
|
||||
* @this {CPUStatePDP10}
|
||||
* @param {number} op
|
||||
* @param {number} acc
|
||||
* @param {number} dev
|
||||
*/
|
||||
PDP10.opCONSZ = function(op, acc)
|
||||
PDP10.opCONSZ = function(op, dev)
|
||||
{
|
||||
this.opUndefined(op);
|
||||
};
|
||||
|
|
@ -4919,23 +4935,35 @@ PDP10.opCONSZ = function(op, acc)
|
|||
*
|
||||
* @this {CPUStatePDP10}
|
||||
* @param {number} op
|
||||
* @param {number} acc
|
||||
* @param {number} dev
|
||||
*/
|
||||
PDP10.opCONSO = function(op, acc)
|
||||
PDP10.opCONSO = function(op, dev)
|
||||
{
|
||||
this.opUndefined(op);
|
||||
};
|
||||
|
||||
/**
|
||||
* opIO(op, acc)
|
||||
* opIO(0o700xxx-0o777xxx): Input-Output Instructions
|
||||
*
|
||||
* From the DEC PDP-10 System Reference Manual (May 1968), p. 2-68:
|
||||
*
|
||||
* The input-output instructions govern all transfers of data to and from the peripheral equipment, and also
|
||||
* perform many operations within the processor. An instruction in the in-out class is designated by 111 in
|
||||
* bits 0-2, ie its left octal digit is 7. Bits 3-9 address the device that is to respond to the instruction.
|
||||
* The format thus allows for 128 codes, two of which, 000 and 004 respectively, address the processor and
|
||||
* priority interrupt, and are used for the console and time share hardware as well. A chart in Appendix A
|
||||
* lists all devices for which codes have been assigned, and gives their mnemonics and DEC option numbers.
|
||||
*
|
||||
* Bits 13-35 are the same as in all other instructions: they are the I, X, and Y parts, which are used to
|
||||
* calculate an effective address, set of conditions, or mask to be used in the execution of the instruction.
|
||||
* The remaining bits, 10-12, select one of the following eight 10 instructions.
|
||||
*
|
||||
* @this {CPUStatePDP10}
|
||||
* @param {number} op
|
||||
* @param {number} acc
|
||||
*/
|
||||
PDP10.opIO = function(op, acc)
|
||||
PDP10.opIO = function(op)
|
||||
{
|
||||
this.opUndefined(op);
|
||||
PDP10.aOpIO_KA10[op & 7].call(this, (op >> 3) & 0o177);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -5687,7 +5715,7 @@ PDP10.aOpXXX_KA10 = [
|
|||
PDP10.opTSOA, // 0o675xxx
|
||||
PDP10.opTDON, // 0o676xxx
|
||||
PDP10.opTSON, // 0o677xxx
|
||||
PDP10.opIO, // 0o700xx
|
||||
PDP10.opIO, // 0o700xxx
|
||||
PDP10.opIO, // 0o701xxx
|
||||
PDP10.opIO, // 0o702xxx
|
||||
PDP10.opIO, // 0o703xxx
|
||||
|
|
@ -5752,3 +5780,14 @@ PDP10.aOpXXX_KA10 = [
|
|||
PDP10.opIO, // 0o776xxx
|
||||
PDP10.opIO // 0o777xxx
|
||||
];
|
||||
|
||||
PDP10.aOpIO_KA10 = [
|
||||
PDP10.opBLKI, // 0o70000x
|
||||
PDP10.opDATAI, // 0o70004x
|
||||
PDP10.opBLKO, // 0o70010x
|
||||
PDP10.opDATAO, // 0o70014x
|
||||
PDP10.opCONO, // 0o70020x
|
||||
PDP10.opCONI, // 0o70024x
|
||||
PDP10.opCONSZ, // 0o70030x
|
||||
PDP10.opCONSO // 0o70034x
|
||||
];
|
||||
|
|
|
|||
|
|
@ -176,7 +176,6 @@ class CPUStatePDP10 extends CPUPDP10 {
|
|||
{
|
||||
this.regEA = this.regRA = this.regOP = 0;
|
||||
this.regPC = this.lastPC = this.addrReset;
|
||||
this.fOverflow = this.fCarry0 = this.fCarry1 = this.fNoDivide = this.fPDOverflow = false;
|
||||
|
||||
/*
|
||||
* This next internal reg is used only with byte instructions, to record an active byte
|
||||
|
|
@ -184,6 +183,11 @@ class CPUStatePDP10 extends CPUPDP10 {
|
|||
*/
|
||||
this.regPS = -1;
|
||||
|
||||
/*
|
||||
* Assorted processor flags
|
||||
*/
|
||||
this.fOverflow = this.fCarry0 = this.fCarry1 = this.fNoDivide = this.fPDOverflow = false;
|
||||
|
||||
/*
|
||||
* This is queried and displayed by the Panel when it's not displaying its own ADDRESS register
|
||||
* (which takes precedence when, for example, you've manually halted the CPU and are independently
|
||||
|
|
@ -191,7 +195,7 @@ class CPUStatePDP10 extends CPUPDP10 {
|
|||
*
|
||||
* We initialize it to the current PC.
|
||||
*/
|
||||
this.lastAddr = this.regPC;
|
||||
this.addrLast = this.regPC;
|
||||
|
||||
/*
|
||||
* opFlags contains various conditions that stepCPU() needs to be aware of.
|
||||
|
|
@ -285,12 +289,18 @@ class CPUStatePDP10 extends CPUPDP10 {
|
|||
state.set(0, [
|
||||
this.regEA,
|
||||
this.regRA,
|
||||
this.regPS,
|
||||
this.regOP,
|
||||
this.regPC,
|
||||
this.regPS,
|
||||
this.opFlags,
|
||||
this.fOverflow,
|
||||
this.fCarry0,
|
||||
this.fCarry1,
|
||||
this.fNoDivide,
|
||||
this.fPDOverflow,
|
||||
this.lastPC,
|
||||
this.lastAddr,
|
||||
this.opFlags
|
||||
this.addrLast,
|
||||
this.addrReset
|
||||
]);
|
||||
state.set(1, []);
|
||||
state.set(2, [this.nTotalCycles, this.getSpeed(), this.flags.autoStart]);
|
||||
|
|
@ -315,12 +325,18 @@ class CPUStatePDP10 extends CPUPDP10 {
|
|||
[
|
||||
this.regEA,
|
||||
this.regRA,
|
||||
this.regPS,
|
||||
this.regOP,
|
||||
this.regPC,
|
||||
this.regPS,
|
||||
this.opFlags,
|
||||
this.fOverflow,
|
||||
this.fCarry0,
|
||||
this.fCarry1,
|
||||
this.fNoDivide,
|
||||
this.fPDOverflow,
|
||||
this.lastPC,
|
||||
this.lastAddr,
|
||||
this.opFlags
|
||||
this.addrLast,
|
||||
this.addrReset
|
||||
] = data[0];
|
||||
|
||||
var a = data[2];
|
||||
|
|
@ -333,6 +349,36 @@ class CPUStatePDP10 extends CPUPDP10 {
|
|||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* readFlags()
|
||||
*
|
||||
* Used to implement the ""CONI APR," instruction; see opCONI().
|
||||
*
|
||||
* @this {CPUStatePDP10}
|
||||
* @return {number}
|
||||
*/
|
||||
readFlags()
|
||||
{
|
||||
var flags = 0;
|
||||
if (this.fOverflow) flags |= PDP10.RFLAG.OVFL;
|
||||
if (this.fPDOverflow) flags |= PDP10.RFLAG.PDOVFL;
|
||||
return flags;
|
||||
}
|
||||
|
||||
/**
|
||||
* writeFlags(w)
|
||||
*
|
||||
* Used to implement the ""CONO APR," instruction; see opCONO().
|
||||
*
|
||||
* @this {CPUStatePDP10}
|
||||
* @param {number} w
|
||||
*/
|
||||
writeFlags(w)
|
||||
{
|
||||
if (w & PDP10.WFLAG.OVFL_CL) this.fOverflow = false;
|
||||
if (w & PDP10.WFLAG.PDOVFL_CL) this.fPDOverflow = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* getOpcode()
|
||||
*
|
||||
|
|
@ -417,7 +463,7 @@ class CPUStatePDP10 extends CPUPDP10 {
|
|||
*/
|
||||
getLastAddr()
|
||||
{
|
||||
return this.lastAddr;
|
||||
return this.addrLast;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -758,7 +804,7 @@ class CPUStatePDP10 extends CPUPDP10 {
|
|||
*/
|
||||
readWordFromPhysical(addr)
|
||||
{
|
||||
return this.bus.getWord(this.lastAddr = addr);
|
||||
return this.bus.getWord(this.addrLast = addr);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -773,7 +819,7 @@ class CPUStatePDP10 extends CPUPDP10 {
|
|||
*/
|
||||
writeWordToPhysical(addr, data)
|
||||
{
|
||||
this.bus.setWord(this.lastAddr = addr, data);
|
||||
this.bus.setWord(this.addrLast = addr, data);
|
||||
return data;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -139,10 +139,10 @@ var PDP10 = {
|
|||
*
|
||||
* Mode Suffix Source Destination
|
||||
* ---- ------ ----- -----------
|
||||
* 0: BASIC None E AC
|
||||
* 1: IMMEDIATE I 0,E AC
|
||||
* 2: MEMORY M AC E
|
||||
* 3: SELF S E E (and AC if A is non-zero)
|
||||
* 0: Basic None E AC
|
||||
* 1: Immediate I 0,E AC
|
||||
* 2: Memory M AC E
|
||||
* 3: Self/Both S or B E E (and AC if A is non-zero)
|
||||
*
|
||||
* Input-output instructions look like:
|
||||
*
|
||||
|
|
@ -191,6 +191,56 @@ var PDP10 = {
|
|||
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
|
||||
},
|
||||
|
||||
/*
|
||||
* Readable CPU (or APR for "Arithmetic Processor") flags provided by the "CONI APR," instruction; see opCONI().
|
||||
*/
|
||||
RFLAG: {
|
||||
PIA: 0o000007, // Priority Interrupt Assignment
|
||||
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
|
||||
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)
|
||||
},
|
||||
|
||||
/*
|
||||
* Writable CPU (or APR for "Arithmetic Processor") flags provided by the "CONO APR," instruction; see opCONO().
|
||||
*
|
||||
* A set bit performs the function shown below, a clear bit does nothing.
|
||||
*/
|
||||
WFLAG: {
|
||||
PIA: 0o000007, // Priority Interrupt Assignment
|
||||
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
|
||||
CLOCK_CL: 0o001000, // Clear Clock Flag
|
||||
CLOCK_IE: 0o002000, // Enable Clock Interrupt
|
||||
CLOCK_ID: 0o004000, // Disable Clock Interrupt
|
||||
NXM_CL: 0o010000, // Clear Non-Existent Memory
|
||||
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
|
||||
},
|
||||
|
||||
/*
|
||||
* 7-bit device codes used by Input-Output instructions; see opIO().
|
||||
*/
|
||||
DEVICES: {
|
||||
APR: 0o000, // Arithmetic Processor
|
||||
PI: 0o001 // Priority Interrupt
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -424,7 +424,9 @@ class MemoryPDP10 {
|
|||
*/
|
||||
readWordMemory(off, addr)
|
||||
{
|
||||
return this.aw[off];
|
||||
var w = this.aw[off];
|
||||
Component.assert(w >= 0 && w < PDP10.WORD_LIMIT);
|
||||
return w;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -437,6 +439,7 @@ class MemoryPDP10 {
|
|||
*/
|
||||
writeWordMemory(w, off, addr)
|
||||
{
|
||||
Component.assert(w >= 0 && w < PDP10.WORD_LIMIT);
|
||||
if (this.aw[off] != w) {
|
||||
this.aw[off] = w;
|
||||
this.fDirty = true;
|
||||
|
|
|
|||
|
|
@ -690,7 +690,8 @@ class CPUStatePDP11 extends CPUPDP11 {
|
|||
this.opLast,
|
||||
this.pswTrap,
|
||||
this.trapReason,
|
||||
this.trapVector
|
||||
this.trapVector,
|
||||
this.addrReset
|
||||
]);
|
||||
state.set(1, [this.getPSW(),this.getMMR0(),this.getMMR1(),this.getMMR2(),this.getMMR3()]);
|
||||
state.set(2, [this.nTotalCycles, this.getSpeed(), this.flags.autoStart]);
|
||||
|
|
@ -731,7 +732,8 @@ class CPUStatePDP11 extends CPUPDP11 {
|
|||
this.opLast,
|
||||
this.pswTrap,
|
||||
this.trapReason,
|
||||
this.trapVector
|
||||
this.trapVector,
|
||||
this.addrReset
|
||||
] = data[0];
|
||||
|
||||
var a = data[1];
|
||||
|
|
|
|||
Loading…
Reference in a new issue