Tested a couple half-word instructions (so far, so good)

This commit is contained in:
Jeff Parsons 2017-02-27 12:25:13 -08:00 committed by Jeff Parsons
commit 17e807ecb6
8 changed files with 479 additions and 579 deletions

View file

@ -540,7 +540,7 @@ class BusPDP10 extends Component {
*
* @this {BusPDP10}
* @param {number} addr is a physical address
* @param {number} w is the word (36-bit) value to write (we truncate it to 16 bits to be safe)
* @param {number} w is the word (36-bit) value to write
*/
setWordDirect(addr, w)
{

View file

@ -2651,7 +2651,7 @@ PDP10.opSETOB = function(op)
};
/**
* opHLL(0o500000): Half Word Left to Left
* opHLL(0o5N0000): Half Word Left to Left
*
* From the DEC PDP-10 System Reference Manual (May 1968), p. 2-3:
*
@ -2668,12 +2668,12 @@ PDP10.opHLL = function(op)
var a = op & PDP10.OPCODE.A_MASK;
var src = this.readWord(this.regEA);
var dst = this.readWord(a);
dst = (dst & PDP10.WORD_MASK) + (src - (src & PDP10.WORD_MASK));
dst = PDP10.setHR(op, dst, src) + (src - (src & PDP10.WORD_MASK));
this.writeWord(a, dst);
};
/**
* opHLLI(0o501000): Half Word Left to Left, Immediate
* opHLLI(0o5N1000): Half Word Left to Left, Immediate
*
* From the DEC PDP-10 System Reference Manual (May 1968), p. 2-3:
*
@ -2692,12 +2692,12 @@ PDP10.opHLLI = function(op)
{
var a = op & PDP10.OPCODE.A_MASK;
var dst = this.readWord(a);
dst = (dst & PDP10.WORD_MASK);
dst = PDP10.setHR(op, dst, 0);
this.writeWord(a, dst);
};
/**
* opHLLM(0o502000): Half Word Left to Left, Memory
* opHLLM(0o5N2000): Half Word Left to Left, Memory
*
* From the DEC PDP-10 System Reference Manual (May 1968), p. 2-3:
*
@ -2714,12 +2714,12 @@ PDP10.opHLLM = function(op)
var a = op & PDP10.OPCODE.A_MASK;
var src = this.readWord(a);
var dst = this.readWord(this.regEA);
dst = (dst & PDP10.WORD_MASK) + (src - (src & PDP10.WORD_MASK));
dst = PDP10.setHR(op, dst, src) + (src - (src & PDP10.WORD_MASK));
this.writeWord(this.regEA, dst);
};
/**
* opHLLS(0o503000): Half Word Left to Left, Self
* opHLLS(0o5N3000): Half Word Left to Left, Self
*
* From the DEC PDP-10 System Reference Manual (May 1968), p. 2-3:
*
@ -2735,7 +2735,13 @@ PDP10.opHLLM = function(op)
*/
PDP10.opHLLS = function(op)
{
if (op & PDP10.OPCODE.A_MASK) PDP10.opHLL.call(this, op);
var dst = this.readWord(this.regEA);
this.writeWord(this.regEA, PDP10.setHR(op, dst, dst));
var a = op & PDP10.OPCODE.A_MASK;
if (a) {
dst = this.readWord(a);
this.writeWord(a, PDP10.setHR(op, dst, dst));
}
};
/**
@ -2831,50 +2837,6 @@ PDP10.opHRLS = function(op)
}
};
/**
* opHLLZ(0o510000)
*
* @this {CPUStatePDP10}
* @param {number} op
*/
PDP10.opHLLZ = function(op)
{
this.opUndefined(op);
};
/**
* opHLLZI(0o511000)
*
* @this {CPUStatePDP10}
* @param {number} op
*/
PDP10.opHLLZI = function(op)
{
this.opUndefined(op);
};
/**
* opHLLZM(0o512000)
*
* @this {CPUStatePDP10}
* @param {number} op
*/
PDP10.opHLLZM = function(op)
{
this.opUndefined(op);
};
/**
* opHLLZS(0o513000)
*
* @this {CPUStatePDP10}
* @param {number} op
*/
PDP10.opHLLZS = function(op)
{
this.opUndefined(op);
};
/**
* opHRLZ(0o514000)
*
@ -2919,50 +2881,6 @@ PDP10.opHRLZS = function(op)
this.opUndefined(op);
};
/**
* opHLLO(0o520000)
*
* @this {CPUStatePDP10}
* @param {number} op
*/
PDP10.opHLLO = function(op)
{
this.opUndefined(op);
};
/**
* opHLLOI(0o521000)
*
* @this {CPUStatePDP10}
* @param {number} op
*/
PDP10.opHLLOI = function(op)
{
this.opUndefined(op);
};
/**
* opHLLOM(0o522000)
*
* @this {CPUStatePDP10}
* @param {number} op
*/
PDP10.opHLLOM = function(op)
{
this.opUndefined(op);
};
/**
* opHLLOS(0o523000)
*
* @this {CPUStatePDP10}
* @param {number} op
*/
PDP10.opHLLOS = function(op)
{
this.opUndefined(op);
};
/**
* opHRLO(0o524000)
*
@ -3007,50 +2925,6 @@ PDP10.opHRLOS = function(op)
this.opUndefined(op);
};
/**
* opHLLE(0o530000)
*
* @this {CPUStatePDP10}
* @param {number} op
*/
PDP10.opHLLE = function(op)
{
this.opUndefined(op);
};
/**
* opHLLEI(0o531000)
*
* @this {CPUStatePDP10}
* @param {number} op
*/
PDP10.opHLLEI = function(op)
{
this.opUndefined(op);
};
/**
* opHLLEM(0o532000)
*
* @this {CPUStatePDP10}
* @param {number} op
*/
PDP10.opHLLEM = function(op)
{
this.opUndefined(op);
};
/**
* opHLLES(0o533000)
*
* @this {CPUStatePDP10}
* @param {number} op
*/
PDP10.opHLLES = function(op)
{
this.opUndefined(op);
};
/**
* opHRLE(0o534000)
*
@ -4355,6 +4229,56 @@ PDP10.opUndefined = function(op)
this.stopCPU();
};
/**
* setHR(op, dst, src)
*
* @param {number} op
* @param {number} dst (36-bit value whose 18-bit right half is either preserved or modified)
* @param {number} src (36-bit value used to determine the sign extension, if any, for the right half of dst)
* @return {number} (updated dst)
*/
PDP10.setHR = function(op, dst, src)
{
switch(op & 0o600) {
case 0o000:
dst = (dst & PDP10.WORD_MASK);
break;
case 0o200:
dst = 0;
break;
case 0o400:
dst = PDP10.WORD_MASK;
break;
case 0o600:
dst = (src > PDP10.MAX_POS? PDP10.WORD_MASK : 0);
break;
}
return dst;
};
/*
* If we want the basic half-word operations to handle all the sub-operations; ie:
*
* None
* Zero-extend
* One-extend
* Sign-extend
*
* then we need to alias all the sub-functions to the corresponding primary functions.
*/
PDP10.opHLLZ = PDP10.opHLL;
PDP10.opHLLZI = PDP10.opHLLI;
PDP10.opHLLZM = PDP10.opHLLM;
PDP10.opHLLZS = PDP10.opHLLS;
PDP10.opHLLO = PDP10.opHLL;
PDP10.opHLLOI = PDP10.opHLLI;
PDP10.opHLLOM = PDP10.opHLLM;
PDP10.opHLLOS = PDP10.opHLLS;
PDP10.opHLLE = PDP10.opHLL;
PDP10.opHLLEI = PDP10.opHLLI;
PDP10.opHLLEM = PDP10.opHLLM;
PDP10.opHLLES = PDP10.opHLLS;
PDP10.aOpXXX_KA10 = [
PDP10.opUUO, // 0o000xxx
PDP10.opUUO, // 0o001xxx

View file

@ -102,6 +102,7 @@ var PDP10 = {
DATA_LIMIT: Math.pow(2, 36),
WORD_SHIFT: Math.pow(2, 18),
WORD_MASK: 0o777777,
MAX_POS: Math.pow(2, 35) - 1,
/*
* PDP-10 opcodes are 36-bit values, most of which use the following layout:

View file

@ -83,9 +83,7 @@ class MemoryPDP10 {
this.type = type || MemoryPDP10.TYPE.NONE;
this.fReadOnly = (type == MemoryPDP10.TYPE.ROM);
this.dbg = null;
this.readBits = this.readBitsDirect = this.readNone;
this.readWord = this.readWordDirect = this.readNone;
this.writeBits = this.writeBitsDirect = this.writeNone;
this.writeWord = this.writeWordDirect = this.writeNone;
this.cReadBreakpoints = this.cWriteBreakpoints = 0;
this.copyBreakpoints(); // initialize the block's Debugger info; the caller will reinitialize
@ -222,13 +220,11 @@ class MemoryPDP10 {
/**
* setAccess(afn, fDirect)
*
* The afn parameter should be a 4-entry function table containing two bits handlers and
* two word handlers. See the static afnMemory table for an example.
* The afn parameter should be a 2-entry function table containing word read and write handlers.
* See the static afnMemory table for an example.
*
* If no function table is specified, a default is selected based on the Memory type;
* similarly, any undefined entries in the table are filled with default handlers that fall
* back to the bits handlers, and if one or both bits handlers are undefined, they default
* to handlers that simply ignore the access.
* If no function table is specified, a default is selected based on the Memory type; similarly,
* any undefined entries in the table are filled with default handlers.
*
* fDirect indicates that both the default AND the direct handlers should be updated. Direct
* handlers normally match the default handlers, except when "checked" handlers are installed;
@ -260,12 +256,10 @@ class MemoryPDP10 {
setReadAccess(afn, fDirect)
{
if (!fDirect || !this.cReadBreakpoints) {
this.readBits = afn[0] || this.readNone;
this.readWord = afn[2] || this.readNone;
this.readWord = afn[0] || this.readNone;
}
if (fDirect || fDirect === undefined) {
this.readBitsDirect = afn[0] || this.readNone;
this.readWordDirect = afn[2] || this.readNone;
this.readWordDirect = afn[0] || this.readNone;
}
}
@ -279,12 +273,10 @@ class MemoryPDP10 {
setWriteAccess(afn, fDirect)
{
if (!fDirect || !this.cWriteBreakpoints) {
this.writeBits = !this.fReadOnly && afn[1] || this.writeNone;
this.writeWord = !this.fReadOnly && afn[3] || this.writeNone;
this.writeWord = !this.fReadOnly && afn[1] || this.writeNone;
}
if (fDirect || fDirect === undefined) {
this.writeBitsDirect = afn[1] || this.writeNone;
this.writeWordDirect = afn[3] || this.writeNone;
this.writeWordDirect = afn[1] || this.writeNone;
}
}
@ -295,7 +287,6 @@ class MemoryPDP10 {
*/
resetReadAccess()
{
this.readBits = this.readBitsDirect;
this.readWord = this.readWordDirect;
}
@ -306,7 +297,6 @@ class MemoryPDP10 {
*/
resetWriteAccess()
{
this.writeBits = this.fReadOnly? this.writeNone : this.writeBitsDirect;
this.writeWord = this.fReadOnly? this.writeNone : this.writeWordDirect;
}
@ -424,27 +414,6 @@ class MemoryPDP10 {
}
}
/**
* readBitsMemory(off, addr, offBits, lenBits)
*
* @this {MemoryPDP10}
* @param {number} off
* @param {number} addr
* @param {number} offBits (the bit position of the right-most bit of the result, using modern bit numbering)
* @param {number} lenBits
* @return {number}
*/
readBitsMemory(off, addr, offBits, lenBits)
{
var w = this.aw[off];
if (offBits + lenBits <= 32) {
w = (w >> offBits) & ((1 << lenBits) - 1);
} else {
w = Math.trunc(w / Math.pow(2, offBits)) % Math.pow(2, lenBits);
}
return w;
}
/**
* readWordMemory(off, addr)
*
@ -458,29 +427,6 @@ class MemoryPDP10 {
return this.aw[off];
}
/**
* writeBitsMemory(bits, off, addr, offBits, lenBits)
*
* @this {MemoryPDP10}
* @param {number} bits (only the right-most lenBits of bits are used, so it doesn't need to be pre-masked)
* @param {number} off
* @param {number} addr
* @param {number} offBits (the bit position of the right-most bit of the result, using modern bit numbering)
* @param {number} lenBits
*/
writeBitsMemory(bits, off, addr, offBits, lenBits)
{
var w = this.aw[off];
var shiftBits = Math.pow(2, offBits);
bits %= Math.pow(2, lenBits);
var v = (w % Math.pow(2, offBits + lenBits));
w = (w - v) + (bits * shiftBits) + (v % shiftBits);
if (this.aw[off] != w) {
this.aw[off] = w;
this.fDirty = true;
}
}
/**
* writeWordMemory(w, off, addr)
*
@ -491,26 +437,10 @@ class MemoryPDP10 {
*/
writeWordMemory(w, off, addr)
{
this.aw[off] = w;
this.fDirty = true;
}
/**
* readBitsChecked(off, addr, offBits, lenBits)
*
* @this {MemoryPDP10}
* @param {number} off
* @param {number} addr
* @param {number} offBits (the bit position of the right-most bit of the result, using modern bit numbering)
* @param {number} lenBits
* @return {number}
*/
readBitsChecked(off, addr, offBits, lenBits)
{
if (DEBUGGER && this.dbg && this.addr != null) {
this.dbg.checkMemoryRead(this.addr + off);
if (this.aw[off] != w) {
this.aw[off] = w;
this.fDirty = true;
}
return this.readBitsDirect(off, addr, offBits, lenBits);
}
/**
@ -529,24 +459,6 @@ class MemoryPDP10 {
return this.readWordDirect(off, addr);
}
/**
* writeBitsChecked(bits, off, addr, offBits, lenBits)
*
* @this {MemoryPDP10}
* @param {number} bits
* @param {number} off
* @param {number} addr
* @param {number} offBits (the bit position of the right-most bit of the result, using modern bit numbering)
* @param {number} lenBits
*/
writeBitsChecked(bits, off, addr, offBits, lenBits)
{
if (DEBUGGER && this.dbg && this.addr != null) {
this.dbg.checkMemoryWrite(this.addr + off);
}
if (this.fReadOnly) this.writeNone(bits, off, addr); else this.writeBitsDirect(bits, off, addr, offBits, lenBits);
}
/**
* writeWordChecked(w, off, addr)
*
@ -587,11 +499,9 @@ MemoryPDP10.idBlock = 0;
/*
* This is the effective definition of afnNone, but we need not fully define it, because setAccess()
* uses these defaults when any of the 4 handlers (ie, 2 bits handlers and 2 word handlers) are undefined.
* uses these defaults when any of the handlers are undefined.
*
MemoryPDP10.afnNone = [
MemoryPDP10.prototype.readNone,
MemoryPDP10.prototype.writeNone,
MemoryPDP10.prototype.readNone,
MemoryPDP10.prototype.writeNone
];
@ -599,15 +509,11 @@ MemoryPDP10.afnNone = [
MemoryPDP10.afnNone = [];
MemoryPDP10.afnMemory = [
MemoryPDP10.prototype.readBitsMemory,
MemoryPDP10.prototype.writeBitsMemory,
MemoryPDP10.prototype.readWordMemory,
MemoryPDP10.prototype.writeWordMemory
];
MemoryPDP10.afnChecked = [
MemoryPDP10.prototype.readBitsChecked,
MemoryPDP10.prototype.writeBitsChecked,
MemoryPDP10.prototype.readWordChecked,
MemoryPDP10.prototype.writeWordChecked
];